From 377c4c21f0e922c0549c3deaea327928bece3b12 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 6 Dec 2017 19:14:24 -0500 Subject: [PATCH 001/615] 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 002/615] 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 003/615] 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 004/615] 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 005/615] 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 006/615] 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 007/615] 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 008/615] 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 009/615] 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 010/615] 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 011/615] + 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 012/615] 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 013/615] 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 014/615] 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 015/615] [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 016/615] 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 017/615] 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 018/615] 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 019/615] 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 020/615] 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 021/615] 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 022/615] 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 023/615] 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 024/615] 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 025/615] 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 026/615] 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 027/615] 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 028/615] 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 029/615] 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 030/615] 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 031/615] 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 032/615] 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 033/615] 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 034/615] 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 035/615] 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 036/615] 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 037/615] 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 038/615] 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 039/615] 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 040/615] 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 041/615] 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 042/615] 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 043/615] 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 044/615] 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 045/615] 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 046/615] 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 047/615] 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 048/615] 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 049/615] 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 050/615] 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 058/615] 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 059/615] 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 060/615] 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 061/615] 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 062/615] 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 063/615] 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 064/615] 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 071/615] 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 072/615] 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 073/615] 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 074/615] 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 075/615] 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 076/615] 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 077/615] 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 078/615] 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 079/615] 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 080/615] 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 081/615] 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 082/615] 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 083/615] 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 084/615] 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 085/615] 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 086/615] 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 087/615] 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 088/615] 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 089/615] 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 090/615] 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 091/615] 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 092/615] 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 093/615] 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 094/615] 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 095/615] 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 096/615] 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 097/615] 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 098/615] 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 099/615] 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 100/615] 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 101/615] 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 102/615] 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 103/615] 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 104/615] 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 105/615] 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 106/615] 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 107/615] 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 108/615] 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 109/615] 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 110/615] 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 111/615] 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 112/615] 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 113/615] 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 114/615] 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 115/615] 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 116/615] 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 117/615] 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 118/615] 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 119/615] 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 120/615] 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 121/615] 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 122/615] 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 123/615] 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 124/615] 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 125/615] 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 126/615] 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 127/615] 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 128/615] 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 129/615] 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 130/615] 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 131/615] 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 132/615] 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 133/615] 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 134/615] 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 135/615] 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 136/615] 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 137/615] 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 138/615] 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 139/615] 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 140/615] [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 141/615] 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 142/615] 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 143/615] 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 144/615] 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 145/615] [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 146/615] 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 147/615] 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 148/615] 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 149/615] 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 150/615] 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 151/615] 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 152/615] 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 153/615] 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 154/615] 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 155/615] 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 156/615] 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 157/615] 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 158/615] 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 159/615] 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 160/615] 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 161/615] 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 162/615] 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 163/615] 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 164/615] 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 165/615] 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 166/615] 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 167/615] 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 168/615] 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 169/615] 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 170/615] 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 171/615] 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 172/615] 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 173/615] 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 174/615] 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 175/615] 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 176/615] 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 177/615] 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 178/615] 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 179/615] 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 180/615] 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 181/615] 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 182/615] 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 183/615] 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 184/615] 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 185/615] 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 186/615] 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 187/615] 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 188/615] 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 189/615] 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 190/615] 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 191/615] 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 192/615] 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 193/615] 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 194/615] 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 195/615] 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 196/615] 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 199/615] 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 200/615] 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 201/615] 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 202/615] 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 203/615] 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 204/615] 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 205/615] 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 206/615] 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 207/615] 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 208/615] 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 209/615] 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 210/615] 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 211/615] 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 212/615] 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 213/615] 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 214/615] [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 215/615] 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 216/615] 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 217/615] 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 218/615] 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 219/615] 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 220/615] 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 221/615] 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 222/615] 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 223/615] 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 224/615] 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 225/615] 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 226/615] 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 227/615] 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 228/615] 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 229/615] 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 230/615] 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 231/615] 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 232/615] 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 233/615] 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 234/615] 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 235/615] 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 236/615] 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 237/615] 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 238/615] 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 239/615] 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 240/615] 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 241/615] 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 242/615] 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 243/615] 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 244/615] 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 245/615] 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 246/615] 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 247/615] 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 248/615] 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 249/615] 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 250/615] 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 251/615] 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 252/615] 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 253/615] 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 254/615] 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 255/615] 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 256/615] 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 257/615] 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 258/615] 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 259/615] 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 260/615] 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 261/615] 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 262/615] 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 263/615] 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 264/615] 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 265/615] 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 266/615] 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 267/615] 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 268/615] 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 269/615] 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 270/615] 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 271/615] 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 272/615] 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 273/615] 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 274/615] 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 275/615] 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 276/615] 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 277/615] 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 278/615] 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 279/615] 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 280/615] 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 281/615] 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 282/615] 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 283/615] 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 284/615] 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 285/615] 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 286/615] 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 287/615] 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 288/615] 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 289/615] 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 290/615] 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 291/615] 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 292/615] 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 293/615] 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 294/615] 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 295/615] 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 296/615] 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 297/615] 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 298/615] 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 299/615] 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 300/615] 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 301/615] =?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 302/615] 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 303/615] 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 304/615] 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 305/615] 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 306/615] [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 307/615] 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 308/615] 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 309/615] 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 310/615] [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 311/615] 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 312/615] 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 313/615] 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 314/615] 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 315/615] 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 316/615] 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 317/615] 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 318/615] 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 319/615] 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 320/615] 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 321/615] 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 322/615] 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 323/615] 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 324/615] 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 325/615] 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 326/615] 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 327/615] 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 328/615] 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 329/615] 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 330/615] 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 331/615] 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 332/615] 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 333/615] 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 334/615] 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 335/615] 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 336/615] 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 337/615] 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 338/615] 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 339/615] 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 340/615] 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 341/615] 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 342/615] 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 343/615] 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 344/615] 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 345/615] 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 346/615] 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 347/615] 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 348/615] 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 349/615] 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 350/615] -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 351/615] 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 352/615] 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 353/615] 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 354/615] 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 355/615] 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 356/615] 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 357/615] 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 358/615] 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 359/615] 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 360/615] 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 361/615] 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 362/615] 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 363/615] 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 364/615] 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 365/615] 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 366/615] 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 367/615] 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 368/615] 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 369/615] 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 370/615] 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 371/615] 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 372/615] 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 373/615] 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 374/615] 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 375/615] 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 376/615] 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 377/615] 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 378/615] 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 379/615] 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 380/615] 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 381/615] 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 382/615] 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 383/615] 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 384/615] 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 385/615] 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 386/615] 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 387/615] 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 388/615] 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 389/615] 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 390/615] 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 391/615] 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 392/615] 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 393/615] 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 394/615] 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 395/615] 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 396/615] 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 397/615] 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 398/615] 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 399/615] 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 400/615] 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 401/615] 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 421/615] 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 422/615] 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 423/615] 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 424/615] 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 425/615] 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 426/615] 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 427/615] 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 428/615] 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 429/615] 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 430/615] 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 431/615] 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 432/615] 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 433/615] 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 434/615] 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 435/615] 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 436/615] 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 437/615] 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 438/615] 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 439/615] 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 440/615] 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 441/615] 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 442/615] 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 443/615] 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 444/615] 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 445/615] 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 446/615] 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 447/615] 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 448/615] 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 449/615] 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 450/615] 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 451/615] 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 452/615] 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 453/615] 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 454/615] 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 455/615] 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 456/615] 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 457/615] 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 458/615] 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 459/615] 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 460/615] 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 461/615] 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 462/615] 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 463/615] 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 464/615] 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 465/615] 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 466/615] 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 467/615] 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 468/615] 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 469/615] 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 470/615] 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 471/615] 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 472/615] 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 473/615] [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 474/615] 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 475/615] 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 476/615] 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 477/615] 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 478/615] 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 479/615] 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 480/615] 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 481/615] 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 482/615] 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 483/615] 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 484/615] 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 485/615] 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 486/615] 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 487/615] 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 488/615] 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 489/615] 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 490/615] 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 491/615] 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 492/615] 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 493/615] 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 494/615] 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 495/615] 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 496/615] 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 497/615] 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 498/615] 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 499/615] 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 500/615] 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 501/615] 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 502/615] 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 503/615] 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 504/615] 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 505/615] 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 506/615] 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 507/615] 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 530/615] 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 531/615] 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 532/615] 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 533/615] 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 534/615] 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 535/615] 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 536/615] 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 537/615] 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 538/615] 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 539/615] 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 540/615] 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 541/615] 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 542/615] 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 543/615] 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 544/615] 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 545/615] 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 546/615] 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 547/615] 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 548/615] 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 549/615] 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 550/615] 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 c45c3f7c2add90375bf30864b659a7a874a6b342 Mon Sep 17 00:00:00 2001 From: Daniel Luxemburg Date: Wed, 18 Jul 2018 12:22:32 -0400 Subject: [PATCH 551/615] 'rebase' --- build/dist/prebid.js | 10 ++++++++++ genius-modules.json | 8 ++++++++ 2 files changed, 18 insertions(+) create mode 100644 build/dist/prebid.js create mode 100644 genius-modules.json diff --git a/build/dist/prebid.js b/build/dist/prebid.js new file mode 100644 index 00000000000..d3af7aa1c35 --- /dev/null +++ b/build/dist/prebid.js @@ -0,0 +1,10 @@ +/* prebid.js v1.16.0 +Updated : 2018-07-18 */ +!(function(d){var s=window.pbjsChunk;window.pbjsChunk=function(e,t,n){for(var r,i,o,a=0,u=[];a`; + 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 554/615] 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 555/615] 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 556/615] 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 557/615] 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 558/615] 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 559/615] 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 560/615] 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 561/615] 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 562/615] 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 563/615] 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 564/615] 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 565/615] 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 566/615] 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 584/615] 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 585/615] 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 586/615] 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 587/615] 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 588/615] 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 589/615] 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 590/615] 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 591/615] 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 592/615] 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 593/615] 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 594/615] 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 595/615] 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 596/615] 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 597/615] 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 598/615] 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 599/615] 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 600/615] 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 601/615] 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 602/615] 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 603/615] 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 604/615] 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 605/615] 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 606/615] 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 607/615] 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 608/615] 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 ` + + + + '):""},a.getIframeDocument=function(e){if(e){var t=void 0;try{t=e.contentWindow?e.contentWindow.document:e.contentDocument.document?e.contentDocument.document:e.contentDocument}catch(e){a.logError("Cannot get iframe document",e)}return t}},a.getValueString=function(e,t,n){return null==t?n:a.isStr(t)?t:a.isNumber(t)?t.toString():void a.logWarn("Unsuported type for param: "+e+" required type: String")};a.getHighestCpm=O("timeToRespond",(function(e,t){return t=d.syncsPerBidder)return c.logWarn('Number of user syncs exceeded for "'+t+'"');if(d.filterSettings){if(function(e,t){var n=d.filterSettings;if(function(e,t){if(e.all&&e[t])return c.logWarn('Detected presence of the "filterSettings.all" and "filterSettings.'+t+'" in userSync config. You cannot mix "all" with "iframe/image" configs; they are mutually exclusive.'),!1;var n=e.all?e.all:e[t],r=e.all?"all":t;if(!n)return!1;var i=n.filter,o=n.bidders;if(i&&"include"!==i&&"exclude"!==i)return c.logWarn('UserSync "filterSettings.'+r+".filter\" setting '"+i+"' is not a valid option; use either 'include' or 'exclude'."),!1;if("*"!==o&&!(Array.isArray(o)&&0\n \n \n prebid.org wrapper\n \n "+(n?"":"")+"\n \n \n \n ")}}},19:function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},2:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.NATIVE="native",t.VIDEO="video",t.BANNER="banner"},20:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=Object.assign||function(e){for(var t=1;tt.max?e:t}),{max:0}),p=(0,v.default)(e.buckets,(function(e){if(n>g.max*r){var t=e.precision;void 0===t&&(t=y),i=(e.max*r).toFixed(t)}else if(n<=e.max*r&&n>=e.min*r)return e}));return p&&(t=n,a=r,u=void 0!==(o=p).precision?o.precision:y,d=o.increment*a,s=o.min*a,c=Math.pow(10,u+2),f=(t*c-s*c)/(d*c),l=Math.floor(f)*d+s,i=(l=Number(l.toFixed(10))).toFixed(u)),i}function m(e){if(o.isEmpty(e)||!e.buckets||!Array.isArray(e.buckets))return!1;var t=!0;return e.buckets.forEach((function(e){void 0!==e.min&&e.max&&e.increment||(t=!1)})),t}t.getPriceBucketString=function(e,t){var n=2(0,S.timestamp)()},function(e){return e&&(e.status&&!(0,T.default)([a,u],e.status)||!e.status)});function B(e,n){var r=[],i=(0,S.groupBy)(e,"adUnitCode");return Object.keys(i).forEach((function(e){var t=(0,S.groupBy)(i[e],"bidderCode");Object.keys(t).forEach((function(e){return r.push(t[e].reduce(n,s()))}))})),r}function s(e){return{adUnitCode:e,cpm:0,adserverTargeting:{},timeToRespond:0}}function c(n){var g={};function p(e){return"string"==typeof e?[e]:_.isArray(e)?e:n.getAdUnitCodes()||[]}function v(){return B(n.getBidsReceived().filter(d).filter(t.isBidNotExpired),S.getOldestHighestCpmBid)}function y(){return n.getStandardBidderAdServerTargeting().map((function(e){return e.key})).concat(w.TARGETING_KEYS).filter(S.uniques)}function m(r,i,e,t){return Object.keys(i.adserverTargeting).filter(o()).forEach((function(e){var t,n;r.length&&r.filter((n=e,function(e){return e.adUnitCode===i.adUnitCode&&e.adserverTargeting[n]})).forEach((t=e,function(e){_.isArray(e.adserverTargeting[t])||(e.adserverTargeting[t]=[e.adserverTargeting[t]]),e.adserverTargeting[t]=e.adserverTargeting[t].concat(i.adserverTargeting[t]).filter(S.uniques),delete i.adserverTargeting[t]}))})),r.push(i),r}function o(){var t=y();return function(e){return-1===t.indexOf(e)}}function b(t){return I({},t.adUnitCode,Object.keys(t.adserverTargeting).filter(o()).map((function(e){return I({},e.substring(0,O),[t.adserverTargeting[e]])})))}return g.resetPresetTargeting=function(e){if((0,S.isGptPubadsDefined)()){var t=p(e),r=n.getAdUnits().filter((function(e){return(0,T.default)(t,e.code)}));window.googletag.pubads().getSlots().forEach((function(n){C.forEach((function(t){r.forEach((function(e){e.code!==n.getAdUnitPath()&&e.code!==n.getSlotElementId()||n.setTargeting(t,null)}))}))}))}},g.getAllTargeting=function(e){var r,t,i,n,o,a,u,d,s,c=1i&&(r=!1)),!r})),r&&e.run(),r}function u(e,t){void 0===e[t]?e[t]=1:e[t]++}},bidsBackAll:E,addWinningBid:function(e){o=o.concat(e)},getWinningBids:function(){return o},getTimeout:function(){return h},getAuctionId:function(){return v},getAuctionStatus:function(){return y},getAdUnits:function(){return d},getAdUnitCodes:function(){return l},getBidRequests:function(){return g},getBidsReceived:function(){return p}}},t.getStandardBidderSettings=u,t.getKeyValueTargetingPairs=m,t.adjustBids=s;var A=n(0),p=n(31),i=n(17),c=n(189),v=n(12),T=n(3),r=n(14),o=n(20),I=a(n(10)),_=a(n(6));function a(e){return e&&e.__esModule?e:{default:e}}var w=r.userSync.syncUsers,C=n(0),O=n(8),B=n(9),N=n(4),R=t.AUCTION_STARTED="started",U=t.AUCTION_IN_PROGRESS="inProgress",D=t.AUCTION_COMPLETED="completed";B.on(N.EVENTS.BID_ADJUSTMENT,(function(e){s(e)}));var j=4,P={},k={},x=[];function f(e,t){t.timeToRespond>e.getTimeout()+T.config.getConfig("timeoutBuffer")&&e.executeCallback(!0)}function y(e,t){B.emit(N.EVENTS.BID_RESPONSE,t),e.addBidReceived(t),f(e,t)}var M=t.addBidResponse=(0,o.createHook)("asyncSeries",(function(e,t){var n,r,i,o,a=this.getBidRequests(),u=this.getAuctionId(),d=(0,A.getBidderRequest)(a,t.bidderCode,e),s=(function(e){var t=e.adUnitCode,n=e.bid,r=e.bidRequest,i=e.auctionId,o=r.start,a=g({},n,{auctionId:i,responseTimestamp:(0,A.timestamp)(),requestTimestamp:o,cpm:parseFloat(n.cpm)||0,bidder:n.bidderCode,adUnitCode:t});a.timeToRespond=a.responseTimestamp-a.requestTimestamp,B.emit(N.EVENTS.BID_ADJUSTMENT,a);var u=r.bids&&(0,I.default)(r.bids,(function(e){return e.adUnitCode==t})),d=u&&u.renderer;d&&d.url&&(a.renderer=v.Renderer.install({url:d.url}),a.renderer.setRender(d.render));var s,c=T.config.getConfig("mediaTypePriceGranularity."+n.mediaType),f=(0,p.getPriceBucketString)(a.cpm,"object"===(void 0===c?"undefined":l(c))?c:T.config.getConfig("customPriceBucket"),T.config.getConfig("currency.granularityMultiplier"));a.pbLg=f.low,a.pbMg=f.med,a.pbHg=f.high,a.pbAg=f.auto,a.pbDg=f.dense,a.pbCg=f.custom,a.bidderCode&&(0 (eg mediaTypes.banner.sizes).");var t=e.mediaTypes;if(t&&t.banner){var n=t.banner;if(n.sizes){var r=_.getAdUnitSizes(e);n.sizes=r,e.sizes=r}else _.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 e.mediaTypes.banner}if(t&&t.video){var i=t.video;if(i.playerSize)if(Array.isArray(i.playerSize)&&1===i.playerSize.length&&i.playerSize.every(u))e.sizes=i.playerSize;else if(u(i.playerSize)){var o=[];o.push(i.playerSize),_.logInfo("Transforming video.playerSize from "+i.playerSize+" to "+o+" so it's in the proper format."),e.sizes=i.playerSize=o}else _.logError("Detected incorrect configuration of mediaTypes.video.playerSize. Please specify only one set of dimensions in a format like: [[640, 480]]. Removing invalid mediaTypes.video.playerSize property from request."),delete e.mediaTypes.video.playerSize}if(t&&t.native){var a=t.native;a.image&&a.image.sizes&&!Array.isArray(a.image.sizes)&&(_.logError("Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request."),delete e.mediaTypes.native.image.sizes),a.image&&a.image.aspect_ratios&&!Array.isArray(a.image.aspect_ratios)&&(_.logError("Please use an array of sizes for native.image.aspect_ratios field. Removing invalid mediaTypes.native.image.aspect_ratios property from request."),delete e.mediaTypes.native.image.aspect_ratios),a.icon&&a.icon.sizes&&!Array.isArray(a.icon.sizes)&&(_.logError("Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request."),delete e.mediaTypes.native.icon.sizes)}})),e},b.callBids=function(e,t,i,o,a,u){if(t.length){var n=t.reduce((function(e,t){return e[Number(void 0!==t.src&&t.src===w.S2S.SRC)].push(t),e}),[[],[]]),r=h(n,2),d=r[0],s=r[1];if(s.length){var c=(0,E.ajaxBuilder)(u,a?{request:a.request.bind(null,"s2s"),done:a.done}:void 0),f=N.bidders,l=B[N.adapter],g=s[0].tid,p=s[0].adUnitsS2SCopy;if(p.forEach((function(n){var e=n.bids.filter((function(t){return(0,I.default)(s,(function(e){return e.bidderCode===t.bidder&&(0,I.default)(e.bids,(function(e){return e.adUnitCode===n.code}))}))}));n.bids=e})),p=p.filter((function(e){return 0\n