From 7bf3be104c01c463ff245a11f892bf54810720bd Mon Sep 17 00:00:00 2001 From: sa1omon Date: Wed, 23 Jan 2019 23:26:26 +0200 Subject: [PATCH 001/436] Add support for multi-format ad units. Add favoredMediaType property to params. --- modules/gamoshiBidAdapter.js | 103 +++++++++++++++++++---------------- modules/gamoshiBidAdapter.md | 46 +++++++++++++++- 2 files changed, 100 insertions(+), 49 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index fa6632f9abb..80aebd3b548 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -1,10 +1,15 @@ import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { config } from '../src/config'; -import { Renderer } from '../src/Renderer'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {config} from '../src/config'; +import {Renderer} from '../src/Renderer'; + +const ENDPOINTS = { + 'cleanmedia': 'https://bidder.cleanmediaads.com', + 'gamoshi': 'https://rtb.gamoshi.io', + 'gambid': 'https://rtb.gamoshi.io', +}; export const helper = { - getTopFrame: function () { try { return window.top === window ? 1 : 0; @@ -12,30 +17,14 @@ export const helper = { } return 0; }, - startsWith: function (str, search) { return str.substr(0, search.length) === search; }, - getTopWindowDomain: function (url) { const domainStart = url.indexOf('://') + '://'.length; return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); - }, - - getTopWindowReferer: function () { - try { - return window.top.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining top window\'s referrer: ', e); - try { - return window.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining current window\'s referrer: ', e); - } - } - return ''; } -} +}; export const spec = { code: 'gamoshi', @@ -43,7 +32,8 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!bid.params.supplyPartnerId && typeof bid.params.supplyPartnerId === 'string' && + return !!bid.params.supplyPartnerId && + typeof bid.params.supplyPartnerId === 'string' && (typeof bid.params['rtbEndpoint'] === 'undefined' || typeof bid.params['rtbEndpoint'] === 'string') && (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number') && @@ -54,17 +44,16 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; - const baseEndpoint = params['rtbEndpoint'] || 'https://rtb.gamoshi.io'; + const baseEndpoint = params['rtbEndpoint'] || ENDPOINTS[bidRequest.bidder] || ENDPOINTS['gamoshi']; const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); - let referer = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - let url = config.getConfig('pageUrl') || referer || utils.getTopWindowUrl(); + let url = config.getConfig('pageUrl') || bidderRequest.refererInfo.referer; const rtbBidRequest = { 'id': auctionId, 'site': { 'domain': helper.getTopWindowDomain(url), 'page': url, - 'ref': helper.getTopWindowReferer() + 'ref': bidderRequest.refererInfo.referer }, 'device': { 'ua': navigator.userAgent @@ -72,7 +61,8 @@ export const spec = { 'imp': [], 'ext': {} }; - if (bidderRequest && bidderRequest.gdprConsent) { + + if (bidderRequest.gdprConsent) { rtbBidRequest.ext.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: bidderRequest.gdprConsent.gdprApplies @@ -88,25 +78,44 @@ export const spec = { 'secure': helper.startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 }; - if (!mediaTypes || mediaTypes.banner) { - imp.banner = { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, - pos: params.pos || 0, - topframe: helper.getTopFrame() - }; - } else if (mediaTypes.video) { - imp.video = { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, - protocols: params.protocols || [1, 2, 3, 4, 5, 6], - pos: params.pos || 0, - topframe: helper.getTopFrame() - }; - } else { + const hasFavoredMediaType = + params.favoredMediaType && this.supportedMediaTypes.includes(params.favoredMediaType); + + if ((!mediaTypes || mediaTypes.banner)) { + if (!hasFavoredMediaType || params.favoredMediaType === 'banner') { + const bannerImp = Object.assign({}, imp, { + banner: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + pos: params.pos || 0, + topframe: helper.getTopFrame() + } + }); + rtbBidRequest.imp.push(bannerImp); + } + } + + if (mediaTypes && mediaTypes.video) { + if (!hasFavoredMediaType || params.favoredMediaType === 'video') { + const videoImp = Object.assign({}, imp, { + video: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + protocols: params.protocols || [1, 2, 3, 4, 5, 6], + pos: params.pos || 0, + ext: { + context: mediaTypes.video.context + } + } + }); + rtbBidRequest.imp.push(videoImp); + } + } + + if (rtbBidRequest.imp.length === 0) { return; } - rtbBidRequest.imp.push(imp); + return {method: 'POST', url: rtbEndpoint, data: rtbBidRequest, bidRequest}; }); }, @@ -120,6 +129,7 @@ export const spec = { const bids = response.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); const outBids = []; + bids.forEach(bid => { const outBid = { requestId: bidRequest.bidRequest.bidId, @@ -129,7 +139,8 @@ export const spec = { ttl: 60 * 10, creativeId: bid.crid, netRevenue: true, - currency: bid.cur || response.cur + currency: bid.cur || response.cur, + adUnitCode: bidRequest.bidRequest.adUnitCode }; if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { outBids.push(Object.assign({}, outBid, {mediaType: 'banner', ad: bid.adm})); @@ -181,7 +192,7 @@ export const spec = { function newRenderer(bidRequest, bid, rendererOptions = {}) { const renderer = Renderer.install({ - url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.gamoshi.io/video/latest/renderer.js', + url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.wlplayer.com/video/latest/renderer.js', config: rendererOptions, loaded: false, }); diff --git a/modules/gamoshiBidAdapter.md b/modules/gamoshiBidAdapter.md index f88248ef668..6e930375059 100644 --- a/modules/gamoshiBidAdapter.md +++ b/modules/gamoshiBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Gamoshi Bid Adapter Module Type: Bidder Adapter -Maintainer: moses@gamoshi.com +Maintainer: salomon@gamoshi.com ``` # Description @@ -47,7 +47,6 @@ var adUnits = [ // Video outstream adUnit { code: 'video-outstream', - sizes: [[300, 250]], mediaTypes: { video: { context: 'outstream', @@ -76,6 +75,47 @@ var adUnits = [ //instl: 0 } }] - } + }, + + // Multi-Format adUnit + { + code: 'banner-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + }, + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'gamoshi', + params: { + + // ID of the supply partner you created in the Gamoshi dashboard + supplyPartnerId: '1253', + + // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here + //rtbEndpoint: 'https://my.custom-whitelabel-domain.io', + + // OPTIONAL: custom bid floor + bidfloor: 0.01, + + // OPTIONAL: if you know the ad position on the page, specify it here + // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) + //adpos: 1, + + // OPTIONAL: whether this is an interstitial placement (0 or 1) + // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) + //instl: 0, + + // OPTIONAL: enable enforcement bids of a specific media type (video, banner) + // in this ad placement + // query: 'key1=value1&k2=value2', + // favoredMediaType: 'video', + } + }] + }, ]; ``` From fed69e9ea81236cc0307eeb58fb3b64ea35f1e40 Mon Sep 17 00:00:00 2001 From: sa1omon Date: Wed, 23 Jan 2019 23:27:58 +0200 Subject: [PATCH 002/436] Add tests for gdpr consent. --- test/spec/modules/gamoshiBidAdapter_spec.js | 136 +++++++++++++++++--- 1 file changed, 118 insertions(+), 18 deletions(-) diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 26d67b70f78..a8e9d49cf07 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -4,6 +4,7 @@ import {helper} from 'modules/gamoshiBidAdapter'; import * as utils from 'src/utils'; import {newBidder} from '../../../src/adapters/bidderFactory'; import {deepClone} from 'src/utils'; + const supplyPartnerId = '123'; const adapter = newBidder(spec); describe('GamoshiAdapter', function () { @@ -79,42 +80,47 @@ describe('GamoshiAdapter', function () { }, 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', - refererInfo: {referer: 'http://examplereferer.com'} + refererInfo: {referer: 'http://examplereferer.com'}, + gdprConsent: { + consentString: 'some string', + gdprApplies: true + } }; it('returns an array', function () { let response; response = spec.buildRequests([]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); - response = spec.buildRequests([bidRequest]); + response = spec.buildRequests([bidRequest], bidRequest); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'a'}); const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'b'}); - response = spec.buildRequests([adUnit1, adUnit2]); + response = spec.buildRequests([adUnit1, adUnit2], bidRequest); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); }); it('targets correct endpoint', function () { let response; - response = spec.buildRequests([bidRequest])[0]; + response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.method).to.equal('POST'); expect(response.url).to.match(new RegExp(`^https://rtb\\.gamoshi\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); expect(response.data.id).to.equal(bidRequest.auctionId); const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gamoshi.io/a12'; - response = spec.buildRequests([bidRequestWithEndpoint])[0]; + response = spec.buildRequests([bidRequestWithEndpoint], bidRequest)[0]; expect(response.url).to.match(new RegExp(`^https://rtb2\\.gamoshi\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); it('builds request correctly', function () { let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); - let response; - response = spec.buildRequests([bidRequest])[0]; + let bidRequest2 = deepClone(bidRequest); + bidRequest2.refererInfo.referer = 'http://www.test.com/page.html'; + let response = spec.buildRequests([bidRequest], bidRequest2)[0]; expect(response.data.site.domain).to.equal('www.test.com'); expect(response.data.site.page).to.equal('http://www.test.com/page.html'); - expect(response.data.site.ref).to.equal(''); + expect(response.data.site.ref).to.equal('http://www.test.com/page.html'); expect(response.data.imp.length).to.equal(1); expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); expect(response.data.imp[0].instl).to.equal(0); @@ -123,15 +129,15 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].bidfloorcur).to.equal('USD'); const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; - response = spec.buildRequests([bidRequestWithInstlEquals1])[0]; + response = spec.buildRequests([bidRequestWithInstlEquals1], bidRequest2)[0]; expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals1.params.instl); const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); bidRequestWithInstlEquals0.params.instl = 1; - response = spec.buildRequests([bidRequestWithInstlEquals0])[0]; + response = spec.buildRequests([bidRequestWithInstlEquals0], bidRequest2)[0]; expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals0.params.instl); const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); bidRequestWithBidfloorEquals1.params.bidfloor = 1; - response = spec.buildRequests([bidRequestWithBidfloorEquals1])[0]; + response = spec.buildRequests([bidRequestWithBidfloorEquals1], bidRequest2)[0]; expect(response.data.imp[0].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); stub.restore(); }); @@ -144,14 +150,14 @@ describe('GamoshiAdapter', function () { sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([bidRequestWithBanner])[0]; + response = spec.buildRequests([bidRequestWithBanner], bidRequest)[0]; expect(response.data.imp[0].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][0]); expect(response.data.imp[0].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][1]); expect(response.data.imp[0].banner.pos).to.equal(0); expect(response.data.imp[0].banner.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; expect(response.data.imp[0].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); @@ -163,16 +169,45 @@ describe('GamoshiAdapter', function () { sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([bidRequestWithVideo])[0]; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][0]); expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][1]); expect(response.data.imp[0].video.pos).to.equal(0); - expect(response.data.imp[0].video.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); + + it('builds request video object correctly with context', function () { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + context: 'instream' + } + }; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('instream'); + bidRequestWithVideo.mediaTypes.video.context = 'outstream'; + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.mediaTypes.video.context = 'outstream'; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('outstream'); + + const bidRequestWithPosEquals2 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals2.mediaTypes.video.context = null; + response = spec.buildRequests([bidRequestWithPosEquals2], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal(null); + }); + + it('builds request with gdpr consent', function () { + let response = spec.buildRequests([bidRequest], bidRequest)[0]; + expect(response.data.ext).to.have.property('gdpr_consent'); + expect(response.data.ext.gdpr_consent.consent_string).to.equal('some string'); + expect(response.data.ext.gdpr_consent.consent_required).to.equal(true); + }); }); describe('interpretResponse', function () { @@ -188,7 +223,7 @@ describe('GamoshiAdapter', function () { 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', 'bidId': '111', - refererInfo: { referer: 'http://examplereferer.com' } + refererInfo: {referer: 'http://examplereferer.com'} }; const videoBidRequest = { @@ -203,7 +238,7 @@ describe('GamoshiAdapter', function () { 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', 'bidId': '111', - refererInfo: { referer: 'http://examplereferer.com' } + refererInfo: {referer: 'http://examplereferer.com'} }; const rtbResponse = { @@ -402,5 +437,70 @@ describe('GamoshiAdapter', function () { const result = spec.interpretResponse({body: videoResponse}, {bidRequest: videoRequest}); expect(result[0].renderer).to.not.equal(undefined); }); + + it('validates in/existing of gdpr consent', function () { + let videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + let gdprConsent = { + gdprApplies: true, + consentString: 'consent string' + }; + let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=consent%20string'); + + gdprConsent.gdprApplies = false; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=missing'); + + videoResponse.ext.utrk[0].url = 'https://rtb.gamoshi.io/pix/1275/scm'; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?gc=missing'); + }); }); }); From a3b285040204bfb6ea1a36b0f74b0a9f9a13491b Mon Sep 17 00:00:00 2001 From: sa1omon Date: Thu, 24 Jan 2019 17:49:43 +0200 Subject: [PATCH 003/436] Add adId to outbids --- modules/gamoshiBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 80aebd3b548..2f7864d5570 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -128,10 +128,11 @@ export const spec = { } const bids = response.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); - const outBids = []; + let outBids = []; bids.forEach(bid => { const outBid = { + adId: bidRequest.bidRequest.adUnitCode, requestId: bidRequest.bidRequest.bidId, cpm: bid.price, width: bid.w, From c53757a0daafe2ef235c2d0780d41e5d1f0c44b8 Mon Sep 17 00:00:00 2001 From: sa1omon Date: Sun, 27 Jan 2019 20:28:04 +0200 Subject: [PATCH 004/436] Modify media type resolving --- modules/gamoshiBidAdapter.js | 39 ++++++++++++------ test/spec/modules/gamoshiBidAdapter_spec.js | 44 ++++++--------------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 2f7864d5570..1a5b115907d 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -23,6 +23,19 @@ export const helper = { getTopWindowDomain: function (url) { const domainStart = url.indexOf('://') + '://'.length; return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); + }, + + getMediaType: function (bid) { + if (bid.ext) { + if (bid.ext.media_type) { + return bid.ext.media_type; + } else if (bid.ext.vast_url) { + return 'video'; + } else { + return 'banner'; + } + } + return 'banner'; } }; @@ -141,18 +154,22 @@ export const spec = { creativeId: bid.crid, netRevenue: true, currency: bid.cur || response.cur, - adUnitCode: bidRequest.bidRequest.adUnitCode + adUnitCode: bidRequest.bidRequest.adUnitCode, + mediaType: helper.getMediaType(bid) + }; - if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { - outBids.push(Object.assign({}, outBid, {mediaType: 'banner', ad: bid.adm})); - } else if (bidRequest.bidRequest.mediaTypes.video) { - const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); - outBids.push(Object.assign({}, outBid, { - mediaType: 'video', - vastUrl: bid.ext.vast_url, - vastXml: bid.adm, - renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined - })); + + if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { + if (outBid.mediaType === 'banner') { + outBids.push(Object.assign({}, outBid, {ad: bid.adm})); + } else if (outBid.mediaType === 'video') { + const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + outBids.push(Object.assign({}, outBid, { + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined + })); + } } }); return outBids; diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index a8e9d49cf07..148a8857f69 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -262,7 +262,7 @@ describe('GamoshiAdapter', function () { 'price': 2.016, 'adid': '579ef31bfa788b9d2000d562', 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', - 'adm': ' ', + 'adm': '', 'adomain': ['aaa.com'], 'cid': '579ef268fa788b9d2000d55c', 'crid': '579ef31bfa788b9d2000d562', @@ -321,38 +321,28 @@ describe('GamoshiAdapter', function () { it('aggregates banner bids from all seat bids', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); const ad0 = response[0], ad1 = response[1]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[1].bid[0].h); expect(ad0.ttl).to.equal(60 * 10); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad0.ad).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); expect(ad0.vastXml).to.be.an('undefined'); - - expect(ad1.requestId).to.equal(bannerBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); - expect(ad1.vastXml).to.be.an('undefined'); + expect(ad0.vastUrl).to.be.an('undefined'); }); it('aggregates video bids from all seat bids', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); - const ad0 = response[0], ad1 = response[1]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(videoBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); @@ -364,18 +354,6 @@ describe('GamoshiAdapter', function () { expect(ad0.ad).to.be.an('undefined'); expect(ad0.vastXml).to.equal(rtbResponse.seatbid[0].bid[0].adm); expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); - - expect(ad1.requestId).to.equal(videoBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.be.an('undefined'); - expect(ad1.vastXml).to.equal(rtbResponse.seatbid[1].bid[0].adm); - expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[1].bid[0].ext.vast_url); }); it('aggregates user-sync pixels', function () { From 65cbdd8796ad15c6cdc7ce1dcdd5845caf515df0 Mon Sep 17 00:00:00 2001 From: sa1omon Date: Mon, 28 Jan 2019 12:06:36 +0200 Subject: [PATCH 005/436] Refactor multi-format ad units handler. --- modules/gamoshiBidAdapter.js | 13 +++++++------ test/spec/modules/gamoshiBidAdapter_spec.js | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 1a5b115907d..4ff304af867 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {config} from '../src/config'; import {Renderer} from '../src/Renderer'; +import {BANNER, VIDEO} from "../src/mediaTypes"; const ENDPOINTS = { 'cleanmedia': 'https://bidder.cleanmediaads.com', @@ -28,14 +29,14 @@ export const helper = { getMediaType: function (bid) { if (bid.ext) { if (bid.ext.media_type) { - return bid.ext.media_type; + return bid.ext.media_type.toLowerCase(); } else if (bid.ext.vast_url) { - return 'video'; + return VIDEO; } else { - return 'banner'; + return BANNER; } } - return 'banner'; + return BANNER; } }; @@ -160,9 +161,9 @@ export const spec = { }; if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { - if (outBid.mediaType === 'banner') { + if (outBid.mediaType === BANNER) { outBids.push(Object.assign({}, outBid, {ad: bid.adm})); - } else if (outBid.mediaType === 'video') { + } else if (outBid.mediaType === VIDEO) { const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); outBids.push(Object.assign({}, outBid, { vastUrl: bid.ext.vast_url, diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 148a8857f69..896271be4d3 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -323,7 +323,7 @@ describe('GamoshiAdapter', function () { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); - const ad0 = response[0], ad1 = response[1]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); From be6207c865dc7a2af459d8a2174d8a993a4528e5 Mon Sep 17 00:00:00 2001 From: mcamustlr <51314002+mcamustlr@users.noreply.github.com> Date: Wed, 12 Jun 2019 18:04:40 +0200 Subject: [PATCH 006/436] Add slimCut bid adapter (#3880) --- modules/slimcutBidAdapter.js | 128 ++++++++++++ modules/slimcutBidAdapter.md | 45 +++++ test/spec/modules/slimcutBidAdapter_spec.js | 212 ++++++++++++++++++++ 3 files changed, 385 insertions(+) create mode 100644 modules/slimcutBidAdapter.js create mode 100644 modules/slimcutBidAdapter.md create mode 100644 test/spec/modules/slimcutBidAdapter_spec.js diff --git a/modules/slimcutBidAdapter.js b/modules/slimcutBidAdapter.js new file mode 100644 index 00000000000..def490d6ab9 --- /dev/null +++ b/modules/slimcutBidAdapter.js @@ -0,0 +1,128 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { ajax } from 'src/ajax'; + +const BIDDER_CODE = 'slimcut'; +const ENDPOINT_URL = '//sb.freeskreen.com/pbr'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['scm'], + supportedMediaTypes: ['video', 'banner'], + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + let isValid = false; + if (typeof bid.params !== 'undefined' && !isNaN(parseInt(utils.getValue(bid.params, 'placementId'))) && parseInt(utils.getValue(bid.params, 'placementId')) > 0) { + isValid = true; + } + return isValid; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const bids = validBidRequests.map(buildRequestObject); + const payload = { + referrer: getReferrerInfo(bidderRequest), + data: bids, + deviceWidth: screen.width + }; + + let gdpr = bidderRequest.gdprConsent; + if (bidderRequest && gdpr) { + let isCmp = (typeof gdpr.gdprApplies === 'boolean') + let isConsentString = (typeof gdpr.consentString === 'string') + payload.gdpr_iab = { + consent: isConsentString ? gdpr.consentString : '', + status: isCmp ? gdpr.gdprApplies : -1 + }; + } + + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, request) { + const bidResponses = []; + serverResponse = serverResponse.body; + + if (serverResponse.responses) { + serverResponse.responses.forEach(function (bid) { + const bidResponse = { + cpm: bid.cpm, + width: bid.width, + height: bid.height, + currency: bid.currency, + netRevenue: bid.netRevenue, + ttl: bid.ttl, + ad: bid.ad, + requestId: bid.requestId, + creativeId: bid.creativeId, + transactionId: bid.tranactionId, + winUrl: bid.winUrl + }; + bidResponses.push(bidResponse); + }); + } + return bidResponses; + }, + + getUserSyncs: function(syncOptions, serverResponses) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//sb.freeskreen.com/async_usersync.html' + }]; + } + return []; + }, + + onBidWon: function(bid) { + ajax(bid.winUrl + bid.cpm, null); + } +} + +function buildRequestObject(bid) { + const reqObj = {}; + let placementId = utils.getValue(bid.params, 'placementId'); + + reqObj.sizes = utils.parseSizesInput(bid.sizes); + reqObj.bidId = utils.getBidIdParameter('bidId', bid); + reqObj.bidderRequestId = utils.getBidIdParameter('bidderRequestId', bid); + reqObj.placementId = parseInt(placementId); + reqObj.adUnitCode = utils.getBidIdParameter('adUnitCode', bid); + reqObj.auctionId = utils.getBidIdParameter('auctionId', bid); + reqObj.transactionId = utils.getBidIdParameter('transactionId', bid); + + return reqObj; +} + +function getReferrerInfo(bidderRequest) { + let ref = window.location.href; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + ref = bidderRequest.refererInfo.referer; + } + return ref; +} + +registerBidder(spec); diff --git a/modules/slimcutBidAdapter.md b/modules/slimcutBidAdapter.md new file mode 100644 index 00000000000..1d83c8cae6f --- /dev/null +++ b/modules/slimcutBidAdapter.md @@ -0,0 +1,45 @@ +# Overview + +**Module Name**: Slimcut Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: support@slimcut.com + +# Description + +Use `slimcut` as bidder. + +`placementId` is required and must be integer. + +The Slimcut adapter requires setup and approval from the Slimcut team. +Please reach out to your account manager for more information. + +# Test Parameters + +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[640, 480]], + bids: [ + { + bidder: "slimcut", + params: { + placementId: 1234 + } + } + ] + } + ]; +``` + +## UserSync example + +``` +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + syncEnabled: true, + syncDelay: 1 + } +}); +``` diff --git a/test/spec/modules/slimcutBidAdapter_spec.js b/test/spec/modules/slimcutBidAdapter_spec.js new file mode 100644 index 00000000000..92649bf3556 --- /dev/null +++ b/test/spec/modules/slimcutBidAdapter_spec.js @@ -0,0 +1,212 @@ +import {expect} from 'chai'; +import {spec} from 'modules/slimcutBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//sb.freeskreen.com/pbr'; +const AD_SCRIPT = '"'; + +describe('slimcutBidAdapter', function() { + const adapter = newBidder(spec); + + describe('inherited functions', function() { + it('exists and is a function', function() { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function() { + let bid = { + 'bidder': 'slimcut', + 'params': { + 'placementId': 83 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '3c871ffa8ef14c', + 'bidderRequestId': 'b41642f1aee381', + 'auctionId': '4e156668c977d7' + }; + + it('should return true when required params found', function() { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when placementId is not valid (letters)', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 'ABCD' + }; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when placementId < 0', function() { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': -1 + }; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when required params are not passed', function() { + let bid = Object.assign({}, bid); + delete bid.params; + + bid.params = {}; + + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function() { + let bidRequests = [ + { + 'bidder': 'teads', + 'params': { + 'placementId': 10433394 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '3c871ffa8ef14c', + 'bidderRequestId': 'b41642f1aee381', + 'auctionId': '4e156668c977d7', + 'deviceWidth': 1680 + } + ]; + + let bidderResquestDefault = { + 'auctionId': '4e156668c977d7', + 'bidderRequestId': 'b41642f1aee381', + 'timeout': 3000 + }; + + it('sends bid request to ENDPOINT via POST', function() { + const request = spec.buildRequests(bidRequests, bidderResquestDefault); + + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); + + it('should send GDPR to endpoint', function() { + let consentString = 'JRJ8RKfDeBNsERRDCSAAZ+A=='; + let bidderRequest = { + 'auctionId': '4e156668c977d7', + 'bidderRequestId': 'b41642f1aee381', + 'timeout': 3000, + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true, + 'vendorData': { + 'hasGlobalConsent': false + } + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.gdpr_iab).to.exist; + expect(payload.gdpr_iab.consent).to.equal(consentString); + }); + + it('should add referer info to payload', function () { + const bidRequest = Object.assign({}, bidRequests[0]) + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + reachedTop: true, + numIframes: 2 + } + } + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.referrer).to.exist; + expect(payload.referrer).to.deep.equal('http://example.com/page.html') + }); + }); + + describe('getUserSyncs', () => { + let bids = { + 'body': { + 'responses': [{ + 'ad': AD_SCRIPT, + 'cpm': 0.5, + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db94', + 'ttl': 360, + 'width': 300, + 'creativeId': 'er2ee', + 'transactionId': 'deadb33f', + 'winUrl': 'https://sb.freeskreen.com/win' + }] + } + }; + + it('should get the correct number of sync urls', () => { + let urls = spec.getUserSyncs({iframeEnabled: true}, bids); + expect(urls.length).to.equal(1); + expect(urls[0].url).to.equal('//sb.freeskreen.com/async_usersync.html'); + }); + + it('should return no url if not iframe enabled', () => { + let urls = spec.getUserSyncs({iframeEnabled: false}, bids); + expect(urls.length).to.equal(0); + }); + }); + + describe('interpretResponse', function() { + let bids = { + 'body': { + 'responses': [{ + 'ad': AD_SCRIPT, + 'cpm': 0.5, + 'currency': 'USD', + 'height': 250, + 'netRevenue': true, + 'requestId': '3ede2a3fa0db94', + 'ttl': 360, + 'width': 300, + 'creativeId': 'er2ee', + 'transactionId': 'deadb33f', + 'winUrl': 'https://sb.freeskreen.com/win' + }] + } + }; + + it('should get correct bid response', function() { + let expectedResponse = [{ + 'cpm': 0.5, + 'width': 300, + 'height': 250, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360, + 'ad': AD_SCRIPT, + 'requestId': '3ede2a3fa0db94', + 'creativeId': 'er2ee', + 'transactionId': 'deadb33f', + 'winUrl': 'https://sb.freeskreen.com/win' + }]; + + let result = spec.interpretResponse(bids); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function() { + let bids = { + 'body': { + 'responses': [] + } + }; + + let result = spec.interpretResponse(bids); + expect(result.length).to.equal(0); + }); + }); +}); From 046a19cf030aeac19f26f3acd676c1e5b89b72be Mon Sep 17 00:00:00 2001 From: Rafal Pastuszak Date: Wed, 12 Jun 2019 21:53:37 +0100 Subject: [PATCH 007/436] feat(unruly-bid-adapter): use bidResponse siteId when configuring the renderer (#3865) * feat(unruly-bid-adapter): use bidResponse siteId when configuring the renderer * feat(unruly-bid-adapter): bail if siteId is missing * feat(unruly-bid-adapter): log (but don't throw) when siteId is no present --- modules/unrulyBidAdapter.js | 16 ++++- test/spec/modules/unrulyBidAdapter_spec.js | 81 +++++++++++++++++++--- 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js index 5647d2cd6a3..580357a1978 100644 --- a/modules/unrulyBidAdapter.js +++ b/modules/unrulyBidAdapter.js @@ -4,9 +4,12 @@ import { registerBidder } from '../src/adapters/bidderFactory' import { VIDEO } from '../src/mediaTypes' function configureUniversalTag (exchangeRenderer) { + if (!exchangeRenderer.config) throw new Error('UnrulyBidAdapter: Missing renderer config.') + if (!exchangeRenderer.config.siteId) throw new Error('UnrulyBidAdapter: Missing renderer siteId.') + parent.window.unruly = parent.window.unruly || {}; parent.window.unruly['native'] = parent.window.unruly['native'] || {}; - parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || exchangeRenderer.siteId; + parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || exchangeRenderer.config.siteId; parent.window.unruly['native'].supplyMode = 'prebid'; } @@ -35,9 +38,18 @@ const serverResponseToBid = (bid, rendererInstance) => ({ const buildPrebidResponseAndInstallRenderer = bids => bids - .filter(serverBid => !!utils.deepAccess(serverBid, 'ext.renderer')) + .filter(serverBid => { + const hasConfig = !!utils.deepAccess(serverBid, 'ext.renderer.config'); + const hasSiteId = !!utils.deepAccess(serverBid, 'ext.renderer.config.siteId'); + + if (!hasConfig) utils.logError(new Error('UnrulyBidAdapter: Missing renderer config.')); + if (!hasSiteId) utils.logError(new Error('UnrulyBidAdapter: Missing renderer siteId.')); + + return hasSiteId + }) .map(serverBid => { const exchangeRenderer = utils.deepAccess(serverBid, 'ext.renderer'); + configureUniversalTag(exchangeRenderer); configureRendererQueue(); diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index e39f9a8e996..cb30fcf1a9d 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -18,7 +18,10 @@ describe('UnrulyAdapter', function () { 'statusCode': statusCode, 'renderer': { 'id': 'unruly_inarticle', - 'config': {}, + 'config': { + 'siteId': 123456, + 'targetingUUID': 'xxx-yyy-zzz' + }, 'url': 'https://video.unrulymedia.com/native/prebid-loader.js' }, 'adUnitCode': adUnitCode @@ -125,10 +128,10 @@ describe('UnrulyAdapter', function () { it('should be a function', function () { expect(typeof adapter.interpretResponse).to.equal('function'); }); - it('should return empty array when serverResponse is undefined', function () { + it('should return [] when serverResponse is undefined', function () { expect(adapter.interpretResponse()).to.deep.equal([]); }); - it('should return empty array when serverResponse has no bids', function () { + it('should return [] when serverResponse has no bids', function () { const mockServerResponse = { body: { bids: [] } }; expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]) }); @@ -157,7 +160,13 @@ describe('UnrulyAdapter', function () { expect(fakeRenderer.setRender.called).to.be.false; const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); - const mockRenderer = { url: 'value: mockRendererURL' }; + const mockRenderer = { + url: 'value: mockRendererURL', + config: { + siteId: 123456, + targetingUUID: 'xxx-yyy-zzz' + } + }; mockReturnedBid.ext.renderer = mockRenderer; const mockServerResponse = createExchangeResponse(mockReturnedBid); @@ -173,6 +182,58 @@ describe('UnrulyAdapter', function () { sinon.assert.calledWithExactly(fakeRenderer.setRender, sinon.match.func) }); + it('should return [] and log if bidResponse renderer config is not available', function () { + sinon.assert.notCalled(utils.logError) + + expect(Renderer.install.called).to.be.false; + expect(fakeRenderer.setRender.called).to.be.false; + + const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockRenderer = { + url: 'value: mockRendererURL' + }; + mockReturnedBid.ext.renderer = mockRenderer; + const mockServerResponse = createExchangeResponse(mockReturnedBid); + + expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]); + + const logErrorCalls = utils.logError.getCalls(); + expect(logErrorCalls.length).to.equal(2); + + const [ configErrorCall, siteIdErrorCall ] = logErrorCalls; + + expect(configErrorCall.args.length).to.equal(1); + expect(configErrorCall.args[0].message).to.equal('UnrulyBidAdapter: Missing renderer config.'); + + expect(siteIdErrorCall.args.length).to.equal(1); + expect(siteIdErrorCall.args[0].message).to.equal('UnrulyBidAdapter: Missing renderer siteId.'); + }); + + it('should return [] and log if siteId is not available', function () { + sinon.assert.notCalled(utils.logError) + + expect(Renderer.install.called).to.be.false; + expect(fakeRenderer.setRender.called).to.be.false; + + const mockReturnedBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); + const mockRenderer = { + url: 'value: mockRendererURL', + config: {} + }; + mockReturnedBid.ext.renderer = mockRenderer; + const mockServerResponse = createExchangeResponse(mockReturnedBid); + + expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]); + + const logErrorCalls = utils.logError.getCalls(); + expect(logErrorCalls.length).to.equal(1); + + const [ siteIdErrorCall ] = logErrorCalls; + + expect(siteIdErrorCall.args.length).to.equal(1); + expect(siteIdErrorCall.args[0].message).to.equal('UnrulyBidAdapter: Missing renderer siteId.'); + }); + it('bid is placed on the bid queue when render is called', function () { const exchangeBid = createOutStreamExchangeBid({ adUnitCode: 'video', vastUrl: 'value: vastUrl' }); const exchangeResponse = createExchangeResponse(exchangeBid); @@ -191,7 +252,7 @@ describe('UnrulyAdapter', function () { expect(sentRendererConfig.vastUrl).to.equal('value: vastUrl'); expect(sentRendererConfig.renderer).to.equal(fakeRenderer); expect(sentRendererConfig.adUnitCode).to.equal('video') - }) + }); it('should ensure that renderer is placed in Prebid supply mode', function () { const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); @@ -237,13 +298,13 @@ describe('UnrulyAdapter', function () { type: 'iframe', url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html' }) - }) + }); it('should append consent params if gdpr does apply and consent is given', () => { const mockConsent = { gdprApplies: true, consentString: 'hello' - } + }; const response = {} const syncOptions = { iframeEnabled: true } const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) @@ -251,14 +312,14 @@ describe('UnrulyAdapter', function () { type: 'iframe', url: 'https://video.unrulymedia.com/iframes/third-party-iframes.html?gdpr=1&gdpr_consent=hello' }) - }) + }); it('should append consent param if gdpr applies and no consent is given', () => { const mockConsent = { gdprApplies: true, consentString: {} - } - const response = {} + }; + const response = {}; const syncOptions = { iframeEnabled: true } const syncs = adapter.getUserSyncs(syncOptions, response, mockConsent) expect(syncs[0]).to.deep.equal({ From 2deb3bebc2302d7bee93b38825745f1dd5ab4ed3 Mon Sep 17 00:00:00 2001 From: Joshua Casingal Date: Wed, 12 Jun 2019 17:04:28 -0400 Subject: [PATCH 008/436] [BID-3479] - Add BidResponse.meta.dspid for OpenX (#3895) * [BID-3479] - Add BidResponse.meta.dspid for OpenX * Update version number to 2.1.7 --- modules/openxBidAdapter.js | 6 +++++- test/spec/modules/openxBidAdapter_spec.js | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 9719fbb635a..8236be8c2e5 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,7 +8,7 @@ import {parse} from '../src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.6'; +const BIDDER_VERSION = '2.1.7'; let shouldSendBoPixel = true; @@ -121,6 +121,10 @@ function createBannerBidResponses(oxResponseObj, {bids, startTime}) { bidResponse.meta.brandId = adUnit.brand_id; } + if (adUnit.adv_id) { + bidResponse.meta.dspid = adUnit.adv_id; + } + bidResponses.push(bidResponse); registerBeacon(BANNER, adUnit, startTime); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index ee8e452f707..0fda846faa1 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1218,6 +1218,10 @@ describe('OpenxAdapter', function () { expect(bid.meta.brandId).to.equal(DEFAULT_TEST_ARJ_AD_UNIT.brand_id); }); + it('should return a brand ID', function () { + expect(bid.meta.dspid).to.equal(DEFAULT_TEST_ARJ_AD_UNIT.adv_id); + }); + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); From f23056def6afe8e72885b90800f3eb428008fe01 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Wed, 12 Jun 2019 17:12:08 -0400 Subject: [PATCH 009/436] kargo session id (#3897) --- modules/kargoBidAdapter.js | 8 ++++++++ test/spec/modules/kargoBidAdapter_spec.js | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 2c602186547..5c3d59bd241 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -23,6 +23,7 @@ export const spec = { bidSizes[bid.bidId] = bid.sizes; }); const transformedParams = Object.assign({}, { + sessionId: spec._getSessionId(), timeout: bidderRequest.timeout, currency: currency, cpmGranularity: 1, @@ -183,6 +184,13 @@ export const spec = { }; }, + _getSessionId() { + if (!spec._sessionId) { + spec._sessionId = spec._generateRandomUuid(); + } + return spec._sessionId; + }, + _generateRandomUuid() { try { // crypto.getRandomValues is supported everywhere but Opera Mini for years diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 5d53a4e9c95..a6779f518a0 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -34,7 +34,7 @@ describe('kargo adapter tests', function () { }); describe('build request', function() { - var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = []; + var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = [], sessionIds = []; beforeEach(function () { undefinedCurrency = false; @@ -212,6 +212,10 @@ describe('kargo adapter tests', function () { setCookie('krg_crb', getEmptyKrgCrbOldStyle()); } + function getSessionId() { + return spec._sessionId; + } + function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { var base = { timeout: 200, @@ -302,6 +306,8 @@ describe('kargo adapter tests', function () { function testBuildRequests(expected) { var request = spec.buildRequests(bids, {timeout: 200, foo: 'bar'}); + expected.sessionId = getSessionId(); + sessionIds.push(expected.sessionId); var krakenParams = JSON.parse(decodeURIComponent(request.data.slice(5))); expect(request.data.slice(0, 5)).to.equal('json='); expect(request.url).to.equal('https://krk.kargo.com/api/v2/bid'); @@ -310,6 +316,14 @@ describe('kargo adapter tests', function () { expect(request.timeout).to.equal(200); expect(request.foo).to.equal('bar'); expect(krakenParams).to.deep.equal(expected); + // Make sure session ID stays the same across requests simulating multiple auctions on one page load + for (let i in sessionIds) { + if (i == 0) { + continue; + } + let sessionId = sessionIds[i]; + expect(sessionIds[0]).to.equal(sessionId); + } } it('works when all params and localstorage and cookies are correctly set', function() { From 7dea69802cfbf384b20223bf397b0a29d25f8c8d Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 12 Jun 2019 15:35:26 -0600 Subject: [PATCH 010/436] allow endpoint configuration for rdn adapter (#3902) --- modules/rdnBidAdapter.js | 3 ++- test/spec/modules/rdnBidAdapter_spec.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/modules/rdnBidAdapter.js b/modules/rdnBidAdapter.js index f93145b5377..d85b307263d 100644 --- a/modules/rdnBidAdapter.js +++ b/modules/rdnBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from '../src/adapters/bidderFactory' import * as utils from '../src/utils' import { BANNER } from '../src/mediaTypes' +import { config } from '../src/config' const BIDDER_CODE = 'rdn' const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h' @@ -14,7 +15,7 @@ export const spec = { const params = bid.params bidRequests.push({ method: 'GET', - url: ENDPOINT, + url: config.getConfig('rdn.endpoint') || ENDPOINT, data: { bi: bid.bidId, t: params.adSpotId, diff --git a/test/spec/modules/rdnBidAdapter_spec.js b/test/spec/modules/rdnBidAdapter_spec.js index 1c5958c8065..1fef1c7bf3d 100644 --- a/test/spec/modules/rdnBidAdapter_spec.js +++ b/test/spec/modules/rdnBidAdapter_spec.js @@ -2,10 +2,20 @@ import { expect } from 'chai' import * as utils from 'src/utils' import { spec } from 'modules/rdnBidAdapter' import { newBidder } from 'src/adapters/bidderFactory' +import {config} from '../../../src/config'; describe('rdnBidAdapter', function() { const adapter = newBidder(spec); const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h'; + let sandbox; + + beforeEach(function() { + config.resetConfig(); + }); + + afterEach(function () { + config.resetConfig(); + }); describe('inherited functions', () => { it('exists and is a function', () => { @@ -53,6 +63,16 @@ describe('rdnBidAdapter', function() { expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET') }) + + it('allows url override', () => { + config.setConfig({ + rdn: { + endpoint: '//test.rakuten.com' + } + }); + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal('//test.rakuten.com'); + }) }); describe('interpretResponse', () => { From c439525732e8cf6acbc0345140efe35a44d1abc5 Mon Sep 17 00:00:00 2001 From: Aleksa Trajkovic Date: Thu, 13 Jun 2019 18:08:45 +0200 Subject: [PATCH 011/436] aardvark adapter, add width & height params (#3892) --- modules/aardvarkBidAdapter.js | 13 +++- test/spec/modules/aardvarkBidAdapter_spec.js | 76 ++++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 81d393a3859..9caaaaa747c 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -29,12 +29,17 @@ export const spec = { var referer = bidderRequest.refererInfo.referer; var pageCategories = []; var tdId = ''; + var width = window.innerWidth; + var height = window.innerHeight; // This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. try { - if (window.top.rtkcategories && Array.isArray(window.top.rtkcategories)) { - pageCategories = window.top.rtkcategories; + var topWin = utils.getWindowTop(); + if (topWin.rtkcategories && Array.isArray(topWin.rtkcategories)) { + pageCategories = topWin.rtkcategories; } + width = topWin.innerWidth; + height = topWin.innerHeight; } catch (e) {} if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { @@ -49,7 +54,9 @@ export const spec = { payload: { version: 1, jsonp: false, - rtkreferer: referer + rtkreferer: referer, + w: width, + h: height }, endpoint: DEFAULT_ENDPOINT }; diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js index 727527acf29..b532fa4264a 100644 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ b/test/spec/modules/aardvarkBidAdapter_spec.js @@ -1,4 +1,5 @@ import { expect } from 'chai'; +import * as utils from 'src/utils'; import { spec, resetUserSync } from 'modules/aardvarkBidAdapter'; describe('aardvarkAdapterTest', function () { @@ -343,4 +344,79 @@ describe('aardvarkAdapterTest', function () { expect(syncs[0].url).to.equal('//sync.rtk.io/cs?g=1&c=BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA'); }); }); + + describe('reading window.top properties', function () { + const bidCategories = ['bcat1', 'bcat2', 'bcat3']; + const bidRequests = [{ + bidder: 'aardvark', + params: { + ai: 'xiby', + sc: 'TdAx', + host: 'adzone.pub.com', + categories: bidCategories + }, + adUnitCode: 'RTK_aaaa', + transactionId: '1b8389fe-615c-482d-9f1a-177fb8f7d5b0', + sizes: [300, 250], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337', + userId: { tdid: 'eff98622-b5fd-44fa-9a49-6e846922d532' } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + + const topWin = { + innerWidth: 1366, + innerHeight: 768, + rtkcategories: ['cat1', 'cat2', 'cat3'] + }; + + let sandbox; + beforeEach(function () { + sandbox = sinon.createSandbox(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + it('should have window.top dimensions', function () { + sandbox.stub(utils, 'getWindowTop').returns(topWin); + + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + expect(requestItem.data.w).to.equal(topWin.innerWidth); + expect(requestItem.data.h).to.equal(topWin.innerHeight); + }); + }); + + it('should have window dimensions, as backup', function () { + sandbox.stub(utils, 'getWindowTop').returns(undefined); + + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + expect(requestItem.data.w).to.equal(window.innerWidth); + expect(requestItem.data.h).to.equal(window.innerHeight); + }); + }); + + it('should have window.top & bid categories', function () { + sandbox.stub(utils, 'getWindowTop').returns(topWin); + + const requests = spec.buildRequests(bidRequests, bidderRequest); + requests.forEach(function (requestItem) { + utils._each(topWin.categories, function (cat) { + expect(requestItem.data.categories).to.contain(cat); + }); + utils._each(bidCategories, function (cat) { + expect(requestItem.data.categories).to.contain(cat); + }); + }); + }); + }); }); From 1301c905ec93a11a8760a44a39aa4c9ab84728c8 Mon Sep 17 00:00:00 2001 From: nwlosinski Date: Thu, 13 Jun 2019 19:12:14 +0200 Subject: [PATCH 012/436] cache buster for user sync (#3838) --- modules/justpremiumBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 6fbf5454b91..f8419f06faf 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -97,9 +97,9 @@ export const spec = { }, getUserSyncs: function getUserSyncs(syncOptions, responses, gdprConsent) { - let url = '//pre.ads.justpremium.com/v/1.0/t/sync' + let url = '//pre.ads.justpremium.com/v/1.0/t/sync' + '?_c=' + 'a' + Math.random().toString(36).substring(7) + Date.now(); if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { - url = url + '?consentString=' + encodeURIComponent(gdprConsent.consentString) + url = url + '&consentString=' + encodeURIComponent(gdprConsent.consentString) } if (syncOptions.iframeEnabled) { pixels.push({ From b269f2c0da8ee69c56edc1bb01aee3b59d2a9771 Mon Sep 17 00:00:00 2001 From: HolzAndrew Date: Thu, 13 Jun 2019 13:14:41 -0400 Subject: [PATCH 013/436] Add bidFloor to Yieldmo Adapter (#3886) * change userid to pubcid * removes consolelogs * removes .txt file * fixes test * make the if statement useful * fix indentation * move return back to the correct place * fix indent --- modules/yieldmoBidAdapter.js | 28 +++++++++++++-------- modules/yieldmoBidAdapter.md | 3 ++- test/spec/modules/yieldmoBidAdapter_spec.js | 21 ++++++++++------ 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index b2d13e88c80..299baf49042 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -43,12 +43,13 @@ export const spec = { bidRequests.forEach((request) => { serverRequest.p.push(addPlacement(request)); - const userId = getUserId(request) - if (userId) { - const pubcid = userId.pubcid; + const pubcid = getPubcId(request) + if (pubcid) { serverRequest.pubcid = pubcid; } else if (request.crumbs) { - serverRequest.pubcid = request.crumbs.pubcid; + if (request.crumbs.pubcid) { + serverRequest.pubcid = request.crumbs.pubcid; + } } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; @@ -103,8 +104,13 @@ function addPlacement(request) { callback_id: request.bidId, sizes: request.sizes } - if (request.params && request.params.placementId) { - placementInfo.ym_placement_id = request.params.placementId + if (request.params) { + if (request.params.placementId) { + placementInfo.ym_placement_id = request.params.placementId; + } + if (request.params.bidFloor) { + placementInfo.bidFloor = request.params.bidFloor; + } } return JSON.stringify(placementInfo); } @@ -311,10 +317,10 @@ function isMraid() { return !!(window.mraid); } -function getUserId(request) { - let userId; - if (request && request.userId && typeof request.userId === 'object') { - userId = request.userId; +function getPubcId(request) { + let pubcid; + if (request && request.userId && request.userId.pubcid && typeof request.userId === 'object') { + pubcid = request.userId.pubcid; } - return userId; + return pubcid; } diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index 8c60202d7ea..7221f2ebdd0 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -23,7 +23,8 @@ var adUnits = [ bids: [{ bidder: 'yieldmo', params: { - placementId: '1779781193098233305' // string with at most 19 characters (may include numbers only) + placementId: '1779781193098233305', // string with at most 19 characters (may include numbers only) + bidFloor: .28 // optional param } }] } diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 12dd87e1517..2a94dc7e5c9 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -9,7 +9,9 @@ describe('YieldmoAdapter', function () { let bid = { bidder: 'yieldmo', - params: {}, + params: { + bidFloor: 0.1 + }, adUnitCode: 'adunit-code', sizes: [[300, 250], [300, 600]], bidId: '30b31c1838de1e', @@ -59,11 +61,13 @@ describe('YieldmoAdapter', function () { it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); bidArray.push({ bidder: 'yieldmo', - params: {}, + params: { + bidFloor: 0.2 + }, adUnitCode: 'adunit-code-1', sizes: [[300, 250], [300, 600]], bidId: '123456789', @@ -77,19 +81,19 @@ describe('YieldmoAdapter', function () { // multiple placements placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]]},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]]}]'); + expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); }); it('should add placement id if given', function () { bidArray[0].params.placementId = 'ym_1293871298'; let placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"}'); - expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"}'); + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); + expect(placementInfo).not.to.include('"ym_placement_id":"ym_0987654321"'); bidArray[1].params.placementId = 'ym_0987654321'; placementInfo = spec.buildRequests(bidArray).data.p; - expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"}'); - expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"}'); + expect(placementInfo).to.include('"ym_placement_id":"ym_1293871298"'); + expect(placementInfo).to.include('"ym_placement_id":"ym_0987654321"'); }); it('should add additional information to data parameter of request', function () { @@ -104,6 +108,7 @@ describe('YieldmoAdapter', function () { expect(data.hasOwnProperty('title')).to.be.true; expect(data.hasOwnProperty('h')).to.be.true; expect(data.hasOwnProperty('w')).to.be.true; + expect(data.hasOwnProperty('pubcid')).to.be.true; }) it('should add pubcid as parameter of request', function () { From 99ea60bfb534e4764b8f9fb41d8d026586ccca78 Mon Sep 17 00:00:00 2001 From: John Salis Date: Thu, 13 Jun 2019 13:33:32 -0400 Subject: [PATCH 014/436] Add beachfront bidder params to set outstream player settings (#3868) * Add beachfront bidder params to set outstream player settings * Add example for outstream player params * Run ci again --- modules/beachfrontBidAdapter.js | 32 +++++----- modules/beachfrontBidAdapter.md | 32 ++++++++++ .../spec/modules/beachfrontBidAdapter_spec.js | 58 +++++++++++++++++++ 3 files changed, 108 insertions(+), 14 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 552413f4878..efc7dfeda8d 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,7 +7,7 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.4'; +const ADAPTER_VERSION = '1.5'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; @@ -143,21 +143,20 @@ function createRenderer(bidRequest) { loaded: false }); - renderer.setRender(outstreamRender); - - return renderer; -} - -function outstreamRender(bid) { - bid.renderer.push(() => { - window.Beachfront.Player(bid.adUnitCode, { - ad_tag_url: bid.vastUrl, - width: bid.width, - height: bid.height, - expand_in_view: false, - collapse_on_complete: true + renderer.setRender(bid => { + bid.renderer.push(() => { + window.Beachfront.Player(bid.adUnitCode, { + adTagUrl: bid.vastUrl, + width: bid.width, + height: bid.height, + expandInView: getPlayerBidParam(bidRequest, 'expandInView', false), + collapseOnComplete: getPlayerBidParam(bidRequest, 'collapseOnComplete', true), + progressColor: getPlayerBidParam(bidRequest, 'progressColor') + }); }); }); + + return renderer; } function getFirstSize(sizes) { @@ -231,6 +230,11 @@ function getBannerBidParam(bid, key) { return utils.deepAccess(bid, 'params.banner.' + key) || utils.deepAccess(bid, 'params.' + key); } +function getPlayerBidParam(bid, key, defaultValue) { + let param = utils.deepAccess(bid, 'params.player.' + key); + return param === undefined ? defaultValue : param; +} + function isVideoBidValid(bid) { return isVideoBid(bid) && getVideoBidParam(bid, 'appId') && getVideoBidParam(bid, 'bidfloor'); } diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index fb14db59710..3f827fe9241 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -86,3 +86,35 @@ Module that connects to Beachfront's demand sources } ]; ``` + +# Outstream Player Params Example +```javascript + var adUnits = [ + { + code: 'test-video-outstream', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [ 640, 360 ] + } + }, + bids: [ + { + bidder: 'beachfront', + params: { + video: { + bidfloor: 0.01, + appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76', + mimes: [ 'video/mp4', 'application/javascript' ] + }, + player: { + progressColor: '#50A8FA', + expandInView: false, + collapseOnComplete: true + } + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 652dae4a74a..f5890cb6475 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -1,4 +1,5 @@ import { expect } from 'chai'; +import sinon from 'sinon'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import { parse as parseUrl } from 'src/url'; @@ -531,6 +532,63 @@ describe('BeachfrontAdapter', function () { url: OUTSTREAM_SRC }); }); + + it('should initialize a player for outstream bids', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [ width, height ] + } + }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + window.Beachfront = { Player: sinon.spy() }; + bidResponse.adUnitCode = bidRequest.adUnitCode; + bidResponse.renderer.render(bidResponse); + sinon.assert.calledWith(window.Beachfront.Player, bidResponse.adUnitCode, sinon.match({ + adTagUrl: bidResponse.vastUrl, + width: bidResponse.width, + height: bidResponse.height, + expandInView: false, + collapseOnComplete: true + })); + delete window.Beachfront; + }); + + it('should configure outstream player settings from the bidder params', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [ width, height ] + } + }; + bidRequest.params.player = { + expandInView: true, + collapseOnComplete: false, + progressColor: 'green' + }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + window.Beachfront = { Player: sinon.spy() }; + bidResponse.adUnitCode = bidRequest.adUnitCode; + bidResponse.renderer.render(bidResponse); + sinon.assert.calledWith(window.Beachfront.Player, bidResponse.adUnitCode, sinon.match(bidRequest.params.player)); + delete window.Beachfront; + }); }); describe('for banner bids', function () { From 72caf9837f2e840690b9c506fd226ed5e5447f60 Mon Sep 17 00:00:00 2001 From: Chris Connors Date: Thu, 13 Jun 2019 14:00:16 -0400 Subject: [PATCH 015/436] Adding Scaleable Analytics Adapter (#3846) * Adding Scaleable Analytics Adapter * Removed commented out code --- modules/scaleableAnalyticsAdapter.js | 153 ++++++++++++++++++ modules/scaleableAnalyticsAdapter.md | 20 +++ .../modules/scaleableAnalyticsAdapter_spec.js | 136 ++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 modules/scaleableAnalyticsAdapter.js create mode 100644 modules/scaleableAnalyticsAdapter.md create mode 100644 test/spec/modules/scaleableAnalyticsAdapter_spec.js diff --git a/modules/scaleableAnalyticsAdapter.js b/modules/scaleableAnalyticsAdapter.js new file mode 100644 index 00000000000..c875dab7e18 --- /dev/null +++ b/modules/scaleableAnalyticsAdapter.js @@ -0,0 +1,153 @@ +/* COPYRIGHT SCALEABLE LLC 2019 */ + +import { ajax } from '../src/ajax'; +import CONSTANTS from '../src/constants.json'; +import adapter from '../src/AnalyticsAdapter'; +import adapterManager from '../src/adapterManager'; +import * as utils from '../src/utils'; + +const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; +const AUCTION_INIT = CONSTANTS.EVENTS.AUCTION_INIT; +const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; +const BID_WON = CONSTANTS.EVENTS.BID_WON; +const AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; + +const URL = 'https://auction.scaleable.ai/'; +const ANALYTICS_TYPE = 'endpoint'; + +let auctionData = {}; + +let scaleableAnalytics = Object.assign({}, + adapter({ + URL, + ANALYTICS_TYPE + }), + { + // Override AnalyticsAdapter functions by supplying custom methods + track({ eventType, args }) { + switch (eventType) { + case AUCTION_INIT: + onAuctionInit(args); + break; + case AUCTION_END: + onAuctionEnd(args); + break; + case BID_WON: + onBidWon(args); + break; + case BID_RESPONSE: + onBidResponse(args); + break; + case BID_TIMEOUT: + onBidTimeout(args); + break; + default: + break; + } + } + } +); + +scaleableAnalytics.config = {}; +scaleableAnalytics.originEnableAnalytics = scaleableAnalytics.enableAnalytics; +scaleableAnalytics.enableAnalytics = config => { + scaleableAnalytics.config = config; + + scaleableAnalytics.originEnableAnalytics(config); + + scaleableAnalytics.enableAnalytics = function _enable() { + return utils.logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); + }; +} + +scaleableAnalytics.getAuctionData = () => { + return auctionData; +}; + +const sendDataToServer = data => ajax(URL, () => {}, JSON.stringify(data)); + +// Track auction initiated +const onAuctionInit = args => { + const config = scaleableAnalytics.config || {options: {}}; + + for (let idx = args.adUnitCodes.length; idx--;) { + const data = { + event: 'request', + site: config.options.site, + adunit: args.adUnitCodes[idx] + }; + + sendDataToServer(data); + } +} + +// Handle all events besides requests and wins +const onAuctionEnd = args => { + for (let adunit in auctionData) { + sendDataToServer(auctionData[adunit]); + } +} + +// Bid Win Events occur after auction end +const onBidWon = args => { + const config = scaleableAnalytics.config || {options: {}}; + + const data = { + event: 'win', + site: config.options.site, + adunit: args.adUnitCode, + code: args.bidderCode, + cpm: args.cpm, + ttr: args.timeToRespond + }; + + sendDataToServer(data); +} + +const onBidResponse = args => { + const config = scaleableAnalytics.config || {options: {}}; + + if (!auctionData[args.adUnitCode]) { + auctionData[args.adUnitCode] = { + event: 'bids', + bids: [], + adunit: args.adUnitCode, + site: config.options.site + }; + } + + const currBidData = { + code: args.bidderCode, + cpm: args.cpm, + ttr: args.timeToRespond + }; + + auctionData[args.adUnitCode].bids.push(currBidData); +} + +const onBidTimeout = args => { + const config = scaleableAnalytics.config || {options: {}}; + + for (let i = args.length; i--;) { + let currObj = args[i]; + + if (!auctionData[currObj.adUnitCode]) { + auctionData[currObj.adUnitCode] = { + event: 'bids', + bids: [], + timeouts: [], + adunit: currObj.adUnitCode, + site: config.options.site + }; + } + + auctionData[currObj.adUnitCode].timeouts.push(currObj.bidder); + } +} + +adapterManager.registerAnalyticsAdapter({ + adapter: scaleableAnalytics, + code: 'scaleable' +}) + +export default scaleableAnalytics; diff --git a/modules/scaleableAnalyticsAdapter.md b/modules/scaleableAnalyticsAdapter.md new file mode 100644 index 00000000000..0f6fbada55a --- /dev/null +++ b/modules/scaleableAnalyticsAdapter.md @@ -0,0 +1,20 @@ +# Overview + +Module Name: Scaleable Analytics Adapter +Module Type: Analytics Adapter +Maintainer: chris@scaleable.ai + +# Description + +Analytics adapter for scaleable.ai. Contact team@scaleable.ai for more information or to sign up for analytics. + +# Implementation Code + +``` +pbjs.enableAnalytics({ + provider: 'scaleable', + options: { + site: '' // Contact Scaleable to receive your unique site id + } +}); +``` diff --git a/test/spec/modules/scaleableAnalyticsAdapter_spec.js b/test/spec/modules/scaleableAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..300f72751a4 --- /dev/null +++ b/test/spec/modules/scaleableAnalyticsAdapter_spec.js @@ -0,0 +1,136 @@ +import scaleableAnalytics from 'modules/scaleableAnalyticsAdapter'; +import { expect } from 'chai'; +import events from 'src/events'; +import CONSTANTS from 'src/constants.json'; +import adapterManager from 'src/adapterManager'; + +const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; +const AUCTION_INIT = CONSTANTS.EVENTS.AUCTION_INIT; +const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; +const BID_WON = CONSTANTS.EVENTS.BID_WON; +const AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; + +describe('Scaleable Analytics Adapter', function() { + const MOCK_DATA = { + adUnitCode: '12345', + site: '5c4fab7a829e955d6c265e72', + bidResponse: { + adUnitCode: '12345', + bidderCode: 'test-code', + cpm: 3.14, + timeToRespond: 285 + }, + bidTimeout: [ + { + adUnitCode: '67890', + bidder: 'test-code' + } + ] + }; + + MOCK_DATA.expectedBidResponse = { + event: 'bids', + bids: [{ + code: MOCK_DATA.bidResponse.bidderCode, + cpm: MOCK_DATA.bidResponse.cpm, + ttr: MOCK_DATA.bidResponse.timeToRespond + }], + adunit: MOCK_DATA.adUnitCode, + site: MOCK_DATA.site + }; + + MOCK_DATA.expectedBidTimeout = { + event: 'bids', + bids: [], + timeouts: [MOCK_DATA.bidTimeout[0].bidder], + adunit: MOCK_DATA.bidTimeout[0].adUnitCode, + site: MOCK_DATA.site + }; + + let xhr; + let requests; + + before(function() { + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + }); + + after(function() { + xhr.restore(); + }); + + describe('Event Handling', function() { + beforeEach(function() { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + + scaleableAnalytics.enableAnalytics({ + provider: 'scaleable', + options: { + site: MOCK_DATA.site + } + }); + }); + + afterEach(function() { + events.getEvents.restore(); + scaleableAnalytics.disableAnalytics(); + }); + + it('should handle the auction init event', function(done) { + events.emit(AUCTION_INIT, { + adUnitCodes: [MOCK_DATA.adUnitCode] + }); + + const result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({ + event: 'request', + site: MOCK_DATA.site, + adunit: MOCK_DATA.adUnitCode + }); + + done(); + }); + + it('should handle the bid response event', function() { + events.emit(BID_RESPONSE, MOCK_DATA.bidResponse); + + const actual = scaleableAnalytics.getAuctionData(); + + expect(actual[MOCK_DATA.adUnitCode]).to.deep.equal(MOCK_DATA.expectedBidResponse); + }); + + it('should handle the bid timeout event', function() { + events.emit(BID_TIMEOUT, MOCK_DATA.bidTimeout); + + const actual = scaleableAnalytics.getAuctionData(); + + expect(actual[MOCK_DATA.bidTimeout[0].adUnitCode]).to.deep.equal(MOCK_DATA.expectedBidTimeout); + }); + + it('should handle the bid won event', function(done) { + events.emit(BID_WON, MOCK_DATA.bidResponse); + + const result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal({ + adunit: MOCK_DATA.adUnitCode, + code: MOCK_DATA.bidResponse.bidderCode, + cpm: MOCK_DATA.bidResponse.cpm, + ttr: MOCK_DATA.bidResponse.timeToRespond, + event: 'win', + site: MOCK_DATA.site + }); + + done(); + }); + + it('should handle the auction end event', function(done) { + events.emit(AUCTION_END, {}); + + const result = JSON.parse(requests[0].requestBody); + expect(result).to.deep.equal(MOCK_DATA.expectedBidResponse); + + done(); + }); + }); +}); From cc2fb2e6d272e2b828f7959d33a6af80db6e2b32 Mon Sep 17 00:00:00 2001 From: Luis Date: Thu, 13 Jun 2019 14:04:44 -0400 Subject: [PATCH 016/436] Fix filepath reference (#3905) --- modules/optimeraBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/optimeraBidAdapter.js b/modules/optimeraBidAdapter.js index ab4c75c1c1f..7025045c7de 100644 --- a/modules/optimeraBidAdapter.js +++ b/modules/optimeraBidAdapter.js @@ -1,4 +1,4 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; +import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'optimera'; const SCORES_BASE_URL = 'https://dyv1bugovvq1g.cloudfront.net/'; From 11a6189c6d715ea7bc349544f781f0a26a91f7d5 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Thu, 13 Jun 2019 15:14:21 -0400 Subject: [PATCH 017/436] Prebid 2.19.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 468b16c0ebb..5125a45ef16 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.19.0-pre", + "version": "2.19.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 43a8c223744a83e11c9bbc894215cc5f996fc9e2 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Thu, 13 Jun 2019 15:38:03 -0400 Subject: [PATCH 018/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5125a45ef16..4a3d8b2c959 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.19.0", + "version": "2.20.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From a27bb7321b680d76e5cebec5e7551064ce7be6e9 Mon Sep 17 00:00:00 2001 From: Chris Cole Date: Mon, 17 Jun 2019 10:19:09 -0700 Subject: [PATCH 019/436] digiTrustIdSystem.js add the synchronous behavior to facade call of DigiTrust.getId. Fix spelling error of facade in code. (#3913) --- modules/digiTrustIdSystem.js | 56 ++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index b587913e1ed..07792cc49d3 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -85,12 +85,12 @@ function writeDigiId(id) { } /** - * Set up a DigiTrust fascade object to mimic the API + * Set up a DigiTrust facade object to mimic the API * */ -function initDigitrustFascade(config) { +function initDigitrustFacade(config) { var _savedId = null; // closure variable for storing Id to avoid additional requests - var fascade = { + var facade = { isClient: true, isMock: true, _internals: { @@ -98,8 +98,10 @@ function initDigitrustFascade(config) { initCallback: null }, getUser: function (obj, callback) { - var cb = callback || noop; - var inter = fascade._internals; + var isAsync = !!isFunc(callback); + var cb = isAsync ? callback : noop; + var errResp = { success: false }; + var inter = facade._internals; inter.callCount++; // wrap the initializer callback, if present @@ -113,10 +115,23 @@ function initDigitrustFascade(config) { } } + if (!isMemberIdValid) { + if (!isAsync) { + return errResp + } else { + cb(errResp); + return; + } + } + if (_savedId != null) { checkCallInitializeCb(_savedId); - cb(_savedId); - return; + if (isAsync) { + cb(_savedId); + return; + } else { + return _savedId; + } } var opts = { @@ -140,14 +155,31 @@ function initDigitrustFascade(config) { } callApi(opts); + + if (!isAsync) { + return errResp; // even if it will be successful later, without a callback we report a "failure in this moment" + } } } if (window && window.DigiTrust == null) { - window.DigiTrust = fascade; + window.DigiTrust = facade; } } +/** + * Tests to see if a member ID is valid within facade + * @param {any} memberId + */ +var isMemberIdValid = function (memberId) { + if (memberId && memberId.length > 0) { + return true; + } else { + utils.logError('[DigiTrust Prebid Client Error] Missing member ID, add the member ID to the function call options'); + return false; + } +}; + /** * Encapsulation of needed info for the callback return. * @@ -237,9 +269,9 @@ function getDigiTrustId(configParams) { getDigiTrustId(configParams); }, 100 * (1 + resultHandler.retries++)); return resultHandler.userIdCallback; - } else if (!isInitialized()) { // Second see if we should build a fascade object + } else if (!isInitialized()) { // Second see if we should build a facade object if (resultHandler.retries >= MAX_RETRIES) { - initDigitrustFascade(configParams); // initialize a fascade object that relies on the AJAX call + initDigitrustFacade(configParams); // initialize a facade object that relies on the AJAX call resultHandler.executeIdRequest(configParams); } else { // use expanding envelope @@ -264,7 +296,7 @@ function initializeDigiTrust(config) { dt.initialize(config.init, config.callback); } else if (dt == null) { // Assume we are already on a delay and DigiTrust is not on page - initDigitrustFascade(config); + initDigitrustFacade(config); } } @@ -278,7 +310,7 @@ function surfaceTestHook() { digitrustIdModule['_testHook'] = testHook; } -testHook.initDigitrustFascade = initDigitrustFascade; +testHook.initDigitrustFacade = initDigitrustFacade; /** @type {Submodule} */ export const digiTrustIdSubmodule = { From 957f0afbc6106117fce7514fac5db6bd03d9345e Mon Sep 17 00:00:00 2001 From: ujuettner Date: Tue, 18 Jun 2019 16:42:36 +0200 Subject: [PATCH 020/436] Feature/remove on set targeting (#3919) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling * default to consentRequired: false when not explicitly given * wip - use onSetTargeting callback * add tests for onSetTargeting callback * fix params and respective tests * Remove onSetTargeting --- modules/orbidderBidAdapter.js | 4 ---- test/spec/modules/orbidderBidAdapter_spec.js | 6 ------ 2 files changed, 10 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index e085a14c6b8..fc6eac6e479 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -74,10 +74,6 @@ export const spec = { this.onHandler(bid, '/win'); }, - onSetTargeting (bid) { - this.onHandler(bid, '/targeting'); - }, - onHandler (bid, route) { const getRefererInfo = detectReferer(window); diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 55f5e2cae4c..4a972c42d30 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -178,12 +178,6 @@ describe('orbidderBidAdapter', () => { expect(ajaxStub.firstCall.args[0].indexOf('https://')).to.equal(0); expect(ajaxStub.firstCall.args[0]).to.equal(`${spec.orbidderHost}/win`); expect(ajaxStub.firstCall.args[1]).to.equal(JSON.stringify(bidObjClone)); - - spec.onSetTargeting(bidObj); - expect(ajaxStub.calledTwice).to.equal(true); - expect(ajaxStub.secondCall.args[0].indexOf('https://')).to.equal(0); - expect(ajaxStub.secondCall.args[0]).to.equal(`${spec.orbidderHost}/targeting`); - expect(ajaxStub.secondCall.args[1]).to.equal(JSON.stringify(bidObjClone)); }); }); From 32d14d0e103b96e129c7b8b0f4ae502bb30617ff Mon Sep 17 00:00:00 2001 From: couchcrew-thomas Date: Tue, 18 Jun 2019 16:59:36 +0200 Subject: [PATCH 021/436] FeedAd bidder adapter (#3891) * added file scaffold * added isBidRequestValid implementation * added local prototype of ad integration * added implementation for placement ID validation * fixed video context filter * applied lint to feedad bid adapter * added unit test for bid request validation * added buildRequest unit test * added unit tests for timeout and bid won callbacks * updated bid request to FeedAd API * added parsing of feedad api bid response * added transmisison of tracking events to FeedAd Api * code cleanup * updated feedad unit tests for buildRequest method * added unit tests for event tracking implementation * added unit test for interpretResponse method * added adapter documentation * added dedicated feedad example page * updated feedad adapter to use live system * updated FeedAd adapter placement ID regex * removed groups from FeedAd adapter placement ID regex * removed dedicated feedad example page * updated imports in FeedAd adapter file to use relative paths * updated FeedAd adapter unit test to use sinon.useFakeXMLHttpRequest() --- modules/feedadBidAdapter.js | 290 ++++++++++++++ modules/feedadBidAdapter.md | 44 +++ test/spec/modules/feedadBidAdapter_spec.js | 433 +++++++++++++++++++++ 3 files changed, 767 insertions(+) create mode 100644 modules/feedadBidAdapter.js create mode 100644 modules/feedadBidAdapter.md create mode 100644 test/spec/modules/feedadBidAdapter_spec.js diff --git a/modules/feedadBidAdapter.js b/modules/feedadBidAdapter.js new file mode 100644 index 00000000000..1e995ee8914 --- /dev/null +++ b/modules/feedadBidAdapter.js @@ -0,0 +1,290 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import {ajax} from '../src/ajax'; + +/** + * Version of the FeedAd bid adapter + * @type {string} + */ +const VERSION = '1.0.0'; + +/** + * @typedef {object} FeedAdApiBidRequest + * @inner + * + * @property {number} ad_type + * @property {string} client_token + * @property {string} placement_id + * @property {string} sdk_version + * @property {boolean} app_hybrid + * + * @property {string} [app_bundle_id] + * @property {string} [app_name] + * @property {object} [custom_params] + * @property {number} [connectivity] + * @property {string} [device_adid] + * @property {string} [device_platform] + */ + +/** + * @typedef {object} FeedAdApiBidResponse + * @inner + * + * @property {string} ad - Ad HTML payload + * @property {number} cpm - number / float + * @property {string} creativeId - ID of creative for tracking + * @property {string} currency - 3-letter ISO 4217 currency-code + * @property {number} height - Height of creative returned in [].ad + * @property {boolean} netRevenue - Is the CPM net (true) or gross (false)? + * @property {string} requestId - bids[].bidId + * @property {number} ttl - Time to live for this ad + * @property {number} width - Width of creative returned in [].ad + */ + +/** + * @typedef {object} FeedAdApiTrackingParams + * @inner + * + * @property app_hybrid {boolean} + * @property client_token {string} + * @property klass {'prebid_bidWon'|'prebid_bidTimeout'} + * @property placement_id {string} + * @property prebid_auction_id {string} + * @property prebid_bid_id {string} + * @property prebid_transaction_id {string} + * @property referer {string} + * @property sdk_version {string} + * @property [app_bundle_id] {string} + * @property [app_name] {string} + * @property [device_adid] {string} + * @property [device_platform] {1|2|3} 1 - Android | 2 - iOS | 3 - Windows + */ + +/** + * Bidder network identity code + * @type {string} + */ +const BIDDER_CODE = 'feedad'; + +/** + * The media types supported by FeedAd + * @type {MediaType[]} + */ +const MEDIA_TYPES = [VIDEO, BANNER]; + +/** + * Tag for logging + * @type {string} + */ +const TAG = '[FeedAd]'; + +/** + * Pattern for valid placement IDs + * @type {RegExp} + */ +const PLACEMENT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]+[a-z0-9]$/; + +const API_ENDPOINT = 'https://api.feedad.com'; +const API_PATH_BID_REQUEST = '/1/prebid/web/bids'; +const API_PATH_TRACK_REQUEST = '/1/prebid/web/events'; + +/** + * Stores temporary auction metadata + * @type {Object.} + */ +const BID_METADATA = {}; + +/** + * Checks if the bid is compatible with FeedAd. + * + * @param {BidRequest} bid - the bid to check + * @return {boolean} true if the bid is valid + */ +function isBidRequestValid(bid) { + const clientToken = utils.deepAccess(bid, 'params.clientToken'); + if (!clientToken || !isValidClientToken(clientToken)) { + utils.logWarn(TAG, "missing or invalid parameter 'clientToken'. found value:", clientToken); + return false; + } + + const placementId = utils.deepAccess(bid, 'params.placementId'); + if (!placementId || !isValidPlacementId(placementId)) { + utils.logWarn(TAG, "missing or invalid parameter 'placementId'. found value:", placementId); + return false; + } + + return true; +} + +/** + * Checks if a client token is valid + * @param {string} clientToken - the client token + * @return {boolean} true if the token is valid + */ +function isValidClientToken(clientToken) { + return typeof clientToken === 'string' && clientToken.length > 0; +} + +/** + * Checks if the given placement id is of a correct format. + * Valid IDs are words of lowercase letters from a to z and numbers from 0 to 9. + * The words can be separated by hyphens or underscores. + * Multiple separators must not follow each other. + * The whole placement ID must not be larger than 256 characters. + * + * @param placementId - the placement id to verify + * @returns if the placement ID is valid. + */ +function isValidPlacementId(placementId) { + return typeof placementId === 'string' && + placementId.length > 0 && + placementId.length <= 256 && + PLACEMENT_ID_PATTERN.test(placementId); +} + +/** + * Checks if the given media types contain unsupported settings + * @param {MediaTypes} mediaTypes - the media types to check + * @return {MediaTypes} the unsupported settings, empty when all types are supported + */ +function filterSupportedMediaTypes(mediaTypes) { + return { + banner: mediaTypes.banner, + video: mediaTypes.video && mediaTypes.video.context === 'outstream' ? mediaTypes.video : undefined, + native: undefined + }; +} + +/** + * Checks if the given media types are empty + * @param {MediaTypes} mediaTypes - the types to check + * @return {boolean} true if the types are empty + */ +function isMediaTypesEmpty(mediaTypes) { + return Object.keys(mediaTypes).every(type => mediaTypes[type] === undefined); +} + +/** + * Creates the bid request params the api expects from the prebid bid request + * @param {BidRequest} request - the validated prebid bid request + * @return {FeedAdApiBidRequest} + */ +function createApiBidRParams(request) { + return { + ad_type: 0, + client_token: request.params.clientToken, + placement_id: request.params.placementId, + sdk_version: `prebid_${VERSION}`, + app_hybrid: false, + }; +} + +/** + * Builds the bid request to the FeedAd Server + * @param {BidRequest[]} validBidRequests - all validated bid requests + * @param {object} bidderRequest - meta information + * @return {ServerRequest|ServerRequest[]} + */ +function buildRequests(validBidRequests, bidderRequest) { + if (!bidderRequest) { + return []; + } + let acceptableRequests = validBidRequests.filter(request => !isMediaTypesEmpty(filterSupportedMediaTypes(request.mediaTypes))); + if (acceptableRequests.length === 0) { + return []; + } + let data = Object.assign({}, bidderRequest, { + bids: acceptableRequests.map(req => { + req.params = createApiBidRParams(req); + return req; + }) + }); + data.bids.forEach(bid => BID_METADATA[bid.bidId] = { + referer: data.refererInfo.referer, + transactionId: bid.transactionId + }); + return { + method: 'POST', + url: `${API_ENDPOINT}${API_PATH_BID_REQUEST}`, + data, + options: { + contentType: 'application/json' + } + }; +} + +/** + * Adapts the FeedAd server response to Prebid format + * @param {ServerResponse} serverResponse - the FeedAd server response + * @param {BidRequest} request - the initial bid request + * @returns {Bid[]} the FeedAd bids + */ +function interpretResponse(serverResponse, request) { + /** + * @type FeedAdApiBidResponse[] + */ + return typeof serverResponse.body === 'string' ? JSON.parse(serverResponse.body) : serverResponse.body; +} + +/** + * Creates the parameters for the FeedAd tracking call + * @param {object} data - prebid data + * @param {'prebid_bidWon'|'prebid_bidTimeout'} klass - type of tracking call + * @return {FeedAdApiTrackingParams|null} + */ +function createTrackingParams(data, klass) { + const bidId = data.bidId || data.requestId; + if (!BID_METADATA.hasOwnProperty(bidId)) { + return null; + } + const {referer, transactionId} = BID_METADATA[bidId]; + delete BID_METADATA[bidId]; + return { + app_hybrid: false, + client_token: data.params[0].clientToken, + placement_id: data.params[0].placementId, + klass, + prebid_auction_id: data.auctionId, + prebid_bid_id: bidId, + prebid_transaction_id: transactionId, + referer, + sdk_version: VERSION + }; +} + +/** + * Creates a tracking handler for the given event type + * @param klass - the event type + * @return {Function} the tracking handler function + */ +function trackingHandlerFactory(klass) { + return (data) => { + if (!data) { + return; + } + let params = createTrackingParams(data, klass); + if (params) { + ajax(`${API_ENDPOINT}${API_PATH_TRACK_REQUEST}`, null, JSON.stringify(params), { + withCredentials: true, + method: 'POST', + contentType: 'application/json' + }); + } + } +} + +/** + * @type {BidderSpec} + */ +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: MEDIA_TYPES, + isBidRequestValid, + buildRequests, + interpretResponse, + onTimeout: trackingHandlerFactory('prebid_bidTimeout'), + onBidWon: trackingHandlerFactory('prebid_bidWon') +}; + +registerBidder(spec); diff --git a/modules/feedadBidAdapter.md b/modules/feedadBidAdapter.md new file mode 100644 index 00000000000..fd57025c29e --- /dev/null +++ b/modules/feedadBidAdapter.md @@ -0,0 +1,44 @@ +# Overview + +``` +Module Name: FeedAd Adapter +Module Type: Bidder Adapter +Maintainer: mail@feedad.com +``` + +# Description + +Prebid.JS adapter that connects to the FeedAd demand sources. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { // supports all banner sizes + sizes: [[300, 250]], + }, + video: { // supports only outstream video + context: 'outstream' + } + }, + bids: [ + { + bidder: "feedad", + params: { + clientToken: 'your-client-token' // see below for more info + placementId: 'your-placement-id' // see below for more info + } + } + ] + } + ]; +``` + +# Required Parameters + +| Parameter | Description | +| --------- | ----------- | +| `clientToken` | Your FeedAd web client token. You can view your client token inside the FeedAd admin panel. | +| `placementId` | You can choose placement IDs yourself. A placement ID should be named after the ad position inside your product. For example, if you want to display an ad inside a list of news articles, you could name it "ad-news-overview".
A placement ID may consist of lowercase `a-z`, `0-9`, `-` and `_`. You do not have to manually create the placement IDs before using them. Just specify them within the code, and they will appear in the FeedAd admin panel after the first request.
[Learn more](/concept/feed_ad/index.html) about Placement IDs and how they are grouped to play the same Creative. | diff --git a/test/spec/modules/feedadBidAdapter_spec.js b/test/spec/modules/feedadBidAdapter_spec.js new file mode 100644 index 00000000000..3432a40eca4 --- /dev/null +++ b/test/spec/modules/feedadBidAdapter_spec.js @@ -0,0 +1,433 @@ +import {expect} from 'chai'; +import {spec} from 'modules/feedadBidAdapter'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes'; +import * as sinon from 'sinon'; + +const CODE = 'feedad'; + +describe('FeedAdAdapter', function () { + describe('Public API', function () { + it('should have the FeedAd bidder code', function () { + expect(spec.code).to.equal(CODE); + }); + it('should only support video and banner ads', function () { + expect(spec.supportedMediaTypes).to.be.a('array'); + expect(spec.supportedMediaTypes).to.include(BANNER); + expect(spec.supportedMediaTypes).to.include(VIDEO); + expect(spec.supportedMediaTypes).not.to.include(NATIVE); + }); + it('should export the BidderSpec functions', function () { + expect(spec.isBidRequestValid).to.be.a('function'); + expect(spec.buildRequests).to.be.a('function'); + expect(spec.interpretResponse).to.be.a('function'); + expect(spec.onTimeout).to.be.a('function'); + expect(spec.onBidWon).to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + it('should detect missing params', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [] + }); + expect(result).to.equal(false); + }); + it('should detect missing client token', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {placementId: 'placement'} + }); + expect(result).to.equal(false); + }); + it('should detect zero length client token', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: '', placementId: 'placement'} + }); + expect(result).to.equal(false); + }); + it('should detect missing placement id', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken'} + }); + expect(result).to.equal(false); + }); + it('should detect zero length placement id', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId: ''} + }); + expect(result).to.equal(false); + }); + it('should detect too long placement id', function () { + var placementId = ''; + for (var i = 0; i < 300; i++) { + placementId += 'a'; + } + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId} + }); + expect(result).to.equal(false); + }); + it('should detect invalid placement id', function () { + [ + 'placement id with spaces', + 'some|id', + 'PLACEMENTID', + 'placeme:ntId' + ].forEach(id => { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId: id} + }); + expect(result).to.equal(false); + }); + }); + it('should accept valid parameters', function () { + let result = spec.isBidRequestValid({ + bidder: 'feedad', + sizes: [], + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }); + expect(result).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidderRequest = { + refererInfo: { + referer: 'the referer' + }, + some: 'thing' + }; + + it('should accept empty lists', function () { + let result = spec.buildRequests([], bidderRequest); + expect(result).to.be.empty; + }); + it('should filter native media types', function () { + let bid = { + code: 'feedad', + mediaTypes: { + native: { + sizes: [[300, 250], [300, 600]], + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result).to.be.empty; + }); + it('should filter video media types without outstream context', function () { + let bid = { + code: 'feedad', + mediaTypes: { + video: { + context: 'instream' + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result).to.be.empty; + }); + it('should pass through outstream video media', function () { + let bid = { + code: 'feedad', + mediaTypes: { + video: { + context: 'outstream' + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.data.bids).to.be.lengthOf(1); + expect(result.data.bids[0]).to.deep.equal(bid); + }); + it('should pass through banner media', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.data.bids).to.be.lengthOf(1); + expect(result.data.bids[0]).to.deep.equal(bid); + }); + it('should detect empty media types', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: undefined, + video: undefined, + native: undefined + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result).to.be.empty; + }); + it('should use POST', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.method).to.equal('POST'); + }); + it('should use the correct URL', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.url).to.equal('https://api.feedad.com/1/prebid/web/bids'); + }); + it('should specify the content type explicitly', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid], bidderRequest); + expect(result.options).to.deep.equal({ + contentType: 'application/json' + }) + }); + it('should include the bidder request', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid, bid, bid], bidderRequest); + expect(result.data).to.deep.include(bidderRequest); + }); + it('should detect missing bidder request parameter', function () { + let bid = { + code: 'feedad', + mediaTypes: { + banner: { + sizes: [[320, 250]] + } + }, + params: {clientToken: 'clientToken', placementId: 'placement-id'} + }; + let result = spec.buildRequests([bid, bid, bid]); + expect(result).to.be.empty; + }); + }); + + describe('interpretResponse', function () { + const body = [{ + foo: 'bar', + sub: { + obj: 5 + } + }, { + bar: 'foo' + }]; + + it('should convert string bodies to JSON', function () { + let result = spec.interpretResponse({body: JSON.stringify(body)}); + expect(result).to.deep.equal(body); + }); + + it('should pass through body objects', function () { + let result = spec.interpretResponse({body}); + expect(result).to.deep.equal(body); + }); + }); + + describe('event tracking calls', function () { + const clientToken = 'clientToken'; + const placementId = 'placement id'; + const auctionId = 'the auction id'; + const bidId = 'the bid id'; + const transactionId = 'the transaction id'; + const referer = 'the referer'; + const bidderRequest = { + refererInfo: { + referer: referer + }, + some: 'thing' + }; + const bid = { + 'bidder': 'feedad', + 'params': { + 'clientToken': 'fupp', + 'placementId': 'prebid-test' + }, + 'crumbs': { + 'pubcid': '6254a85f-bded-489a-9736-83c45d45ef1d' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ + 300, + 250 + ] + ] + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': transactionId, + 'sizes': [ + [ + 300, + 250 + ] + ], + 'bidId': bidId, + 'bidderRequestId': '10739fe6fe2127', + 'auctionId': '5ac67dff-d971-4b56-84a3-345a87a1f786', + 'src': 'client', + 'bidRequestsCount': 1 + }; + const timeoutData = { + 'bidId': bidId, + 'bidder': 'feedad', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'auctionId': auctionId, + 'params': [ + { + 'clientToken': clientToken, + 'placementId': placementId + } + ], + 'timeout': 3000 + }; + const bidWonData = { + 'bidderCode': 'feedad', + 'width': 300, + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '3a4529aa05114d', + 'requestId': bidId, + 'mediaType': 'banner', + 'source': 'client', + 'cpm': 0.5, + 'ad': 'ad content', + 'ttl': 60, + 'creativeId': 'feedad-21-0', + 'netRevenue': true, + 'currency': 'EUR', + 'auctionId': auctionId, + 'responseTimestamp': 1558365914596, + 'requestTimestamp': 1558365914506, + 'bidder': 'feedad', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'timeToRespond': 90, + 'pbLg': '0.50', + 'pbMg': '0.50', + 'pbHg': '0.50', + 'pbAg': '0.50', + 'pbDg': '0.50', + 'pbCg': '', + 'size': '300x250', + 'adserverTargeting': { + 'hb_bidder': 'feedad', + 'hb_adid': '3a4529aa05114d', + 'hb_pb': '0.50', + 'hb_size': '300x250', + 'hb_source': 'client', + 'hb_format': 'banner' + }, + 'status': 'rendered', + 'params': [ + { + 'clientToken': clientToken, + 'placementId': placementId + } + ] + }; + const cases = [ + ['onTimeout', timeoutData, 'prebid_bidTimeout'], + ['onBidWon', bidWonData, 'prebid_bidWon'], + ]; + + cases.forEach(([name, data, eventKlass]) => { + let subject = spec[name]; + describe(name + ' handler', function () { + let xhr; + let requests; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = xhr => requests.push(xhr); + }); + + afterEach(function () { + xhr.restore(); + }); + + it('should do nothing on empty data', function () { + subject(undefined); + subject(null); + expect(requests.length).to.equal(0); + }); + + it('should do nothing when bid metadata is not set', function () { + subject(data); + expect(requests.length).to.equal(0); + }); + + it('should send tracking params when correct metadata was set', function () { + spec.buildRequests([bid], bidderRequest); + let expectedData = { + app_hybrid: false, + client_token: clientToken, + placement_id: placementId, + klass: eventKlass, + prebid_auction_id: auctionId, + prebid_bid_id: bidId, + prebid_transaction_id: transactionId, + referer, + sdk_version: '1.0.0' + }; + subject(data); + expect(requests.length).to.equal(1); + let call = requests[0]; + expect(call.url).to.equal('https://api.feedad.com/1/prebid/web/events'); + expect(JSON.parse(call.requestBody)).to.deep.equal(expectedData); + expect(call.method).to.equal('POST'); + expect(call.requestHeaders).to.include({'Content-Type': 'application/json;charset=utf-8'}); + }) + }); + }); + }); +}); From e00a5fed44882535146fe058388f2207a42b09d2 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 18 Jun 2019 12:04:44 -0400 Subject: [PATCH 022/436] Fix #3813 move auctionEnd events so it always executes when auction completes (#3841) * move auctionEnd events so it always executes * remove some commented code --- src/auction.js | 25 +++++++++++++------------ test/spec/auctionmanager_spec.js | 11 +++++++++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/auction.js b/src/auction.js index 1d758997035..a1e8c33adfb 100644 --- a/src/auction.js +++ b/src/auction.js @@ -140,7 +140,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a clearTimeout(_timer); } - if (_callback != null) { + if (_auctionEnd === undefined) { let timedOutBidders = []; if (timedOut) { utils.logMessage(`Auction ${_auctionId} timedOut`); @@ -150,17 +150,19 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a } } - try { - _auctionStatus = AUCTION_COMPLETED; - _auctionEnd = Date.now(); - - events.emit(CONSTANTS.EVENTS.AUCTION_END, getProperties()); + _auctionStatus = AUCTION_COMPLETED; + _auctionEnd = Date.now(); - const adUnitCodes = _adUnitCodes; - const bids = _bidsReceived - .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) - .reduce(groupByPlacement, {}); - _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); + events.emit(CONSTANTS.EVENTS.AUCTION_END, getProperties()); + try { + if (_callback != null) { + const adUnitCodes = _adUnitCodes; + const bids = _bidsReceived + .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) + .reduce(groupByPlacement, {}); + _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); + _callback = null; + } } catch (e) { utils.logError('Error executing bidsBackHandler', null, e); } finally { @@ -175,7 +177,6 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a syncUsers(userSyncConfig.syncDelay); } } - _callback = null; } } diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 2d8ee562ce4..577b1bec333 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -1,4 +1,4 @@ -import { getKeyValueTargetingPairs, auctionCallbacks } from 'src/auction'; +import { getKeyValueTargetingPairs, auctionCallbacks, AUCTION_COMPLETED } from 'src/auction'; import CONSTANTS from 'src/constants.json'; import { adjustBids } from 'src/auction'; import * as auctionModule from 'src/auction'; @@ -783,7 +783,8 @@ describe('auctionmanager.js', function () { server.restore(); events.emit.restore(); }); - it('should emit BID_TIMEOUT for timed out bids', function (done) { + + it('should emit BID_TIMEOUT and AUCTION_END for timed out bids', function (done) { const spec1 = mockBidder(BIDDER_CODE, [bids[0]]); registerBidder(spec1); const spec2 = mockBidder(BIDDER_CODE1, [bids[1]]); @@ -797,6 +798,12 @@ describe('auctionmanager.js', function () { const timedOutBids = bidTimeoutCall.args[1]; assert.equal(timedOutBids.length, 1); assert.equal(timedOutBids[0].bidder, BIDDER_CODE1); + + const auctionEndCall = eventsEmitSpy.withArgs(CONSTANTS.EVENTS.AUCTION_END).getCalls()[0]; + const auctionProps = auctionEndCall.args[1]; + assert.equal(auctionProps.adUnits, adUnits); + assert.equal(auctionProps.timeout, 20); + assert.equal(auctionProps.auctionStatus, AUCTION_COMPLETED) done(); } auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: auctionCallback, cbTimeout: 20}); From 155011facb35664dfaa4e1dde01e4943167119bb Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 18 Jun 2019 12:14:39 -0400 Subject: [PATCH 023/436] fix import paths for various adapters (#3921) --- modules/advenueBidAdapter.js | 6 +++--- modules/bidphysicsBidAdapter.js | 2 +- modules/cedatoBidAdapter.js | 6 +++--- modules/digiTrustIdSystem.js | 2 +- modules/emx_digitalBidAdapter.js | 10 +++++----- modules/imonomyBidAdapter.js | 4 ++-- modules/loopmeBidAdapter.js | 6 +++--- modules/mgidBidAdapter.js | 4 ++-- modules/microadBidAdapter.js | 4 ++-- modules/open8BidAdapter.js | 6 +++--- modules/otmBidAdapter.js | 4 ++-- modules/prebidmanagerAnalyticsAdapter.js | 4 ++-- modules/reklamstoreBidAdapter.js | 6 +++--- modules/slimcutBidAdapter.js | 6 +++--- modules/smartrtbBidAdapter.js | 4 ++-- modules/sortableAnalyticsAdapter.js | 14 +++++++------- modules/timBidAdapter.js | 6 +++--- modules/yieldoneBidAdapter.js | 2 +- 18 files changed, 48 insertions(+), 48 deletions(-) diff --git a/modules/advenueBidAdapter.js b/modules/advenueBidAdapter.js index 3e7711cca0d..6dc5856eacb 100644 --- a/modules/advenueBidAdapter.js +++ b/modules/advenueBidAdapter.js @@ -1,6 +1,6 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; -import * as utils from 'src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; +import * as utils from '../src/utils'; const BIDDER_CODE = 'advenue'; const URL_MULTI = '//ssp.advenuemedia.co.uk/?c=o&m=multi'; diff --git a/modules/bidphysicsBidAdapter.js b/modules/bidphysicsBidAdapter.js index 260a473c631..9f1dc83d427 100644 --- a/modules/bidphysicsBidAdapter.js +++ b/modules/bidphysicsBidAdapter.js @@ -1,4 +1,4 @@ -import {registerBidder} from 'src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; import * as utils from '../src/utils'; import {BANNER} from '../src/mediaTypes'; diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index 78bb7b45c7b..c367c57fc25 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'cedato'; const BID_URL = '//h.cedatoplayer.com/hb'; diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 07792cc49d3..454e6864846 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -11,7 +11,7 @@ // import { config } from 'src/config'; import * as utils from '../src/utils' -import { ajax } from 'src/ajax'; +import { ajax } from '../src/ajax'; import { attachIdSystem } from '../modules/userId'; // import { getGlobal } from 'src/prebidGlobal'; diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 75ce47aae0a..69e02d5c860 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -1,8 +1,8 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, VIDEO } from 'src/mediaTypes'; -import { config } from 'src/config'; -import { Renderer } from 'src/Renderer'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import { config } from '../src/config'; +import { Renderer } from '../src/Renderer'; import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; diff --git a/modules/imonomyBidAdapter.js b/modules/imonomyBidAdapter.js index fa3ad0cfea2..9a0d29a1374 100644 --- a/modules/imonomyBidAdapter.js +++ b/modules/imonomyBidAdapter.js @@ -1,5 +1,5 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'imonomy'; const ENDPOINT = '//b.imonomy.com/openrtb/hb/00000'; diff --git a/modules/loopmeBidAdapter.js b/modules/loopmeBidAdapter.js index fb2f891d3b0..fcfe1fd0687 100644 --- a/modules/loopmeBidAdapter.js +++ b/modules/loopmeBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const LOOPME_ENDPOINT = 'https://loopme.me/api/hb'; diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index e1b15ef4b51..c6744d28f45 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -1,7 +1,7 @@ -import {registerBidder} from 'src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; import * as utils from '../src/utils'; import * as urlUtils from '../src/url'; -import {BANNER, NATIVE} from 'src/mediaTypes'; +import {BANNER, NATIVE} from '../src/mediaTypes'; import {config} from '../src/config'; const DEFAULT_CUR = 'USD'; const BIDDER_CODE = 'mgid'; diff --git a/modules/microadBidAdapter.js b/modules/microadBidAdapter.js index d42e4053fda..391be2c465b 100644 --- a/modules/microadBidAdapter.js +++ b/modules/microadBidAdapter.js @@ -1,5 +1,5 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'microad'; diff --git a/modules/open8BidAdapter.js b/modules/open8BidAdapter.js index be616d0ec30..3c2b94a528a 100644 --- a/modules/open8BidAdapter.js +++ b/modules/open8BidAdapter.js @@ -1,8 +1,8 @@ -import { Renderer } from 'src/Renderer'; +import { Renderer } from '../src/Renderer'; import {ajax} from '../src/ajax'; import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { VIDEO, BANNER } from 'src/mediaTypes'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { VIDEO, BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'open8'; const URL = '//as.vt.open8.com/v1/control/prebid'; diff --git a/modules/otmBidAdapter.js b/modules/otmBidAdapter.js index 57ac414c7b6..ddb4d356f5c 100644 --- a/modules/otmBidAdapter.js +++ b/modules/otmBidAdapter.js @@ -1,5 +1,5 @@ -import {BANNER} from 'src/mediaTypes'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import {BANNER} from '../src/mediaTypes'; +import {registerBidder} from '../src/adapters/bidderFactory'; export const spec = { code: 'otm', diff --git a/modules/prebidmanagerAnalyticsAdapter.js b/modules/prebidmanagerAnalyticsAdapter.js index eb9ad344253..f3474abe95a 100644 --- a/modules/prebidmanagerAnalyticsAdapter.js +++ b/modules/prebidmanagerAnalyticsAdapter.js @@ -9,8 +9,8 @@ const DEFAULT_EVENT_URL = 'https://endpoint.prebidmanager.com/endpoint' const analyticsType = 'endpoint'; const analyticsName = 'Prebid Manager Analytics: '; -var utils = require('src/utils'); -var CONSTANTS = require('src/constants.json'); +var utils = require('../src/utils'); +var CONSTANTS = require('../src/constants.json'); let ajax = ajaxBuilder(0); var _VERSION = 1; diff --git a/modules/reklamstoreBidAdapter.js b/modules/reklamstoreBidAdapter.js index 49f08ab0473..2a659ec0f07 100644 --- a/modules/reklamstoreBidAdapter.js +++ b/modules/reklamstoreBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'reklamstore'; const ENDPOINT_URL = '//ads.rekmob.com/m/prebid'; diff --git a/modules/slimcutBidAdapter.js b/modules/slimcutBidAdapter.js index def490d6ab9..1f52e2cbc30 100644 --- a/modules/slimcutBidAdapter.js +++ b/modules/slimcutBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { ajax } from 'src/ajax'; +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { ajax } from '../src/ajax'; const BIDDER_CODE = 'slimcut'; const ENDPOINT_URL = '//sb.freeskreen.com/pbr'; diff --git a/modules/smartrtbBidAdapter.js b/modules/smartrtbBidAdapter.js index 561ce58e016..1cdef1c474b 100644 --- a/modules/smartrtbBidAdapter.js +++ b/modules/smartrtbBidAdapter.js @@ -1,5 +1,5 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'smartrtb'; function getDomain () { diff --git a/modules/sortableAnalyticsAdapter.js b/modules/sortableAnalyticsAdapter.js index 4682dc09b49..17458065f9a 100644 --- a/modules/sortableAnalyticsAdapter.js +++ b/modules/sortableAnalyticsAdapter.js @@ -1,10 +1,10 @@ -import adapter from 'src/AnalyticsAdapter'; -import CONSTANTS from 'src/constants.json'; -import adapterManager from 'src/adapterManager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {getGlobal} from 'src/prebidGlobal'; -import { config } from 'src/config'; +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import * as utils from '../src/utils'; +import {ajax} from '../src/ajax'; +import {getGlobal} from '../src/prebidGlobal'; +import { config } from '../src/config'; const DEFAULT_PROTOCOL = 'https'; const DEFAULT_HOST = 'pa.deployads.com'; diff --git a/modules/timBidAdapter.js b/modules/timBidAdapter.js index 0539f37deef..449254671f4 100644 --- a/modules/timBidAdapter.js +++ b/modules/timBidAdapter.js @@ -1,7 +1,7 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; import * as bidfactory from '../src/bidfactory'; -var CONSTANTS = require('src/constants.json'); +var CONSTANTS = require('../src/constants.json'); const BIDDER_CODE = 'tim'; function parseBidRequest(bidRequest) { diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index 1e6abf22838..1caf44e790f 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -1,7 +1,7 @@ import * as utils from '../src/utils'; import {config} from '../src/config'; import {registerBidder} from '../src/adapters/bidderFactory'; -import { Renderer } from 'src/Renderer'; +import { Renderer } from '../src/Renderer'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'yieldone'; From 96e3b321bd47aa111611194a6c41c05b1f60839e Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 18 Jun 2019 10:49:40 -0600 Subject: [PATCH 024/436] add --analyze arg for webpack bundle analyzing (#3914) --- package-lock.json | 517 ++++++++++++++++++++++++++++++++++++++++------ package.json | 1 + webpack.conf.js | 35 ++-- 3 files changed, 482 insertions(+), 71 deletions(-) diff --git a/package-lock.json b/package-lock.json index d313ff22ea0..199aff8c33b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.16.0-pre", + "version": "2.20.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -922,6 +922,12 @@ } } }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -1194,6 +1200,12 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", @@ -2670,6 +2682,18 @@ "callsite": "1.0.0" } }, + "bfj": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", + "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "check-types": "^7.3.0", + "hoopy": "^0.1.2", + "tryer": "^1.0.0" + } + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -3108,7 +3132,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3262,6 +3286,12 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "check-types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "dev": true + }, "chokidar": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", @@ -3480,7 +3510,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -3622,6 +3652,15 @@ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -3649,6 +3688,12 @@ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4534,6 +4579,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, "electron-to-chromium": { "version": "1.3.124", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", @@ -4585,7 +4636,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4599,7 +4650,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4615,7 +4666,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4635,7 +4686,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5326,7 +5377,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5535,6 +5586,249 @@ "homedir-polyfill": "^1.0.1" } }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -5733,6 +6027,12 @@ "minimatch": "^3.0.3" } }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -5865,7 +6165,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", "dev": true }, "flush-write-stream": { @@ -5951,6 +6251,12 @@ "samsam": "~1.1" } }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -6074,8 +6380,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6099,15 +6404,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6124,22 +6427,19 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6270,8 +6570,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6285,7 +6584,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6302,7 +6600,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6311,15 +6608,13 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6340,7 +6635,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6429,8 +6723,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6444,7 +6737,6 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6540,8 +6832,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6583,7 +6874,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6605,7 +6895,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6654,15 +6943,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true, - "optional": true + "dev": true } } }, @@ -7337,7 +7624,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7354,7 +7641,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -7764,6 +8051,16 @@ "glogg": "^1.0.0" } }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + } + }, "handlebars": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", @@ -8037,6 +8334,12 @@ "parse-passwd": "^1.0.0" } }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "dev": true + }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -8057,7 +8360,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8286,6 +8589,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "dev": true + }, "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -9053,7 +9362,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9678,7 +9987,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9691,7 +10000,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", "dev": true }, "debug": { @@ -10132,6 +10441,12 @@ } } }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -10141,6 +10456,12 @@ "readable-stream": "^2.0.1" } }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -10228,7 +10549,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10264,7 +10585,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10851,6 +11172,12 @@ "mimic-fn": "^1.0.0" } }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", + "dev": true + }, "opn": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", @@ -10872,7 +11199,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11433,6 +11760,16 @@ "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", "dev": true }, + "proxy-addr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -12145,7 +12482,7 @@ "rfdc": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", "dev": true }, "rgb2hex": { @@ -12614,7 +12951,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -12628,7 +12965,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12651,7 +12988,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -12673,7 +13010,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12689,7 +13026,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -12701,7 +13038,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -12819,7 +13156,7 @@ }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -12953,7 +13290,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13420,6 +13757,12 @@ "through2": "^2.0.3" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -13474,6 +13817,12 @@ "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", "dev": true }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -13954,7 +14303,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14023,6 +14372,12 @@ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -14565,6 +14920,50 @@ } } }, + "webpack-bundle-analyzer": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", + "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-walk": "^6.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.10", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, "webpack-core": { "version": "0.6.9", "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", @@ -14594,7 +14993,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 4a3d8b2c959..11d5ee5901f 100755 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "wdio-spec-reporter": "^0.1.5", "webdriverio": "^4.13.2", "webpack": "^3.0.0", + "webpack-bundle-analyzer": "^3.3.2", "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, diff --git a/webpack.conf.js b/webpack.conf.js index 9518b972b1b..61cdf82df32 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -3,12 +3,34 @@ var path = require('path'); var webpack = require('webpack'); var helpers = require('./gulpHelpers'); var RequireEnsureWithoutJsonp = require('./plugins/RequireEnsureWithoutJsonp.js'); +var { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +var argv = require('yargs').argv; // list of module names to never include in the common bundle chunk var neverBundle = [ 'AnalyticsAdapter.js' ]; +var plugins = [ + new RequireEnsureWithoutJsonp() +]; + +if (argv.analyze) { + plugins.push( + new BundleAnalyzerPlugin() + ) +} + +plugins.push( // this plugin must be last so it can be easily removed for karma unit tests + new webpack.optimize.CommonsChunkPlugin({ + name: 'prebid', + filename: 'prebid-core.js', + minChunks: function(module, count) { + return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) + } + }) +); + module.exports = { devtool: 'source-map', resolve: { @@ -43,16 +65,5 @@ module.exports = { } ] }, - plugins: [ - new RequireEnsureWithoutJsonp(), - - // this plugin must be last so it can be easily removed for karma unit tests - new webpack.optimize.CommonsChunkPlugin({ - name: 'prebid', - filename: 'prebid-core.js', - minChunks: function(module, count) { - return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) - } - }) - ] + plugins }; From e00524a51bc9b22d7ca06c3c5eb5fb6d17095e6a Mon Sep 17 00:00:00 2001 From: Michael Rooke Date: Tue, 18 Jun 2019 12:50:17 -0400 Subject: [PATCH 025/436] Standardize permission bits (#3872) * Standardize the perimssion bits used for modules - Most adapters use 664 (i.e. read/write, but are not executable), but some use 775. Make all adapters use 664. * Update link in documentation --- CONTRIBUTING.md | 2 +- modules/advangelistsBidAdapter.js | 0 modules/advangelistsBidAdapter.md | 0 modules/cpmstarBidAdapter.js | 0 modules/cpmstarBidAdapter.md | 0 modules/criteoBidAdapter.js | 0 modules/criteoBidAdapter.md | 0 modules/danmarketBidAdapter.md | 0 modules/fairtradeBidAdapter.md | 0 modules/gridBidAdapter.md | 0 modules/gxoneBidAdapter.md | 0 modules/oneVideoBidAdapter.md | 0 modules/saraBidAdapter.md | 0 modules/sekindoUMBidAdapter.md | 0 modules/supply2BidAdapter.md | 0 modules/trustxBidAdapter.md | 0 modules/visxBidAdapter.js | 0 modules/visxBidAdapter.md | 0 18 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 modules/advangelistsBidAdapter.js mode change 100755 => 100644 modules/advangelistsBidAdapter.md mode change 100755 => 100644 modules/cpmstarBidAdapter.js mode change 100755 => 100644 modules/cpmstarBidAdapter.md mode change 100755 => 100644 modules/criteoBidAdapter.js mode change 100755 => 100644 modules/criteoBidAdapter.md mode change 100755 => 100644 modules/danmarketBidAdapter.md mode change 100755 => 100644 modules/fairtradeBidAdapter.md mode change 100755 => 100644 modules/gridBidAdapter.md mode change 100755 => 100644 modules/gxoneBidAdapter.md mode change 100755 => 100644 modules/oneVideoBidAdapter.md mode change 100755 => 100644 modules/saraBidAdapter.md mode change 100755 => 100644 modules/sekindoUMBidAdapter.md mode change 100755 => 100644 modules/supply2BidAdapter.md mode change 100755 => 100644 modules/trustxBidAdapter.md mode change 100755 => 100644 modules/visxBidAdapter.js mode change 100755 => 100644 modules/visxBidAdapter.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b82b249fa36..9c00a2bf51a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ commit your changes, and [open a pull request](https://help.github.com/articles/ master branch. Pull requests must have 80% code coverage before beign considered for merge. -Additional details about the process can be found [here](./pr_review.md). +Additional details about the process can be found [here](./PR_REVIEW.md). ## Issues [prebid.org](http://prebid.org/) contains documentation that may help answer questions you have about using Prebid.js. diff --git a/modules/advangelistsBidAdapter.js b/modules/advangelistsBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/advangelistsBidAdapter.md b/modules/advangelistsBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/cpmstarBidAdapter.js b/modules/cpmstarBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/cpmstarBidAdapter.md b/modules/cpmstarBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/criteoBidAdapter.md b/modules/criteoBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/danmarketBidAdapter.md b/modules/danmarketBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/fairtradeBidAdapter.md b/modules/fairtradeBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/gridBidAdapter.md b/modules/gridBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/gxoneBidAdapter.md b/modules/gxoneBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/saraBidAdapter.md b/modules/saraBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/sekindoUMBidAdapter.md b/modules/sekindoUMBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/supply2BidAdapter.md b/modules/supply2BidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/trustxBidAdapter.md b/modules/trustxBidAdapter.md old mode 100755 new mode 100644 diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js old mode 100755 new mode 100644 diff --git a/modules/visxBidAdapter.md b/modules/visxBidAdapter.md old mode 100755 new mode 100644 From 48d365a5a029fbe6885aece6193e15cc6820440b Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 18 Jun 2019 15:45:48 -0400 Subject: [PATCH 026/436] Prebid 2.20.0 release --- package-lock.json | 2933 +++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 1758 insertions(+), 1177 deletions(-) diff --git a/package-lock.json b/package-lock.json index 199aff8c33b..4c03303a050 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0-pre", + "version": "2.20.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", - "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", - "@babel/helpers": "^7.4.3", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -36,12 +36,12 @@ } }, "@babel/generator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", - "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", "dev": true, "requires": { - "@babel/types": "^7.4.0", + "@babel/types": "^7.4.4", "jsesc": "^2.5.1", "lodash": "^4.17.11", "source-map": "^0.5.0", @@ -68,24 +68,24 @@ } }, "@babel/helper-call-delegate": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.0.tgz", - "integrity": "sha512-SdqDfbVdNQCBp3WhK2mNdDvHd3BD6qbmIc43CAyjnsfCmgHMeqgDcM3BzY2lchi7HBJGJ2CVdynLWbezaE4mmQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.0", - "@babel/traverse": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/helper-define-map": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.0.tgz", - "integrity": "sha512-wAhQ9HdnLIywERVcSvX40CEJwKdAa1ID4neI9NXQPDOHwwA+57DqwLiPEVy2AIyWzAk0CQ8qx4awO0VUURwLtA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.0", + "@babel/types": "^7.4.4", "lodash": "^4.17.11" } }, @@ -120,12 +120,12 @@ } }, "@babel/helper-hoist-variables": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.0.tgz", - "integrity": "sha512-/NErCuoe/et17IlAQFKWM24qtyYYie7sFIrW/tIQXpck6vAu2hhtYYsKLBWQV+BQZMbcIYPU/QMYuTufrY4aQw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", "dev": true, "requires": { - "@babel/types": "^7.4.0" + "@babel/types": "^7.4.4" } }, "@babel/helper-member-expression-to-functions": { @@ -147,16 +147,16 @@ } }, "@babel/helper-module-transforms": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.3.tgz", - "integrity": "sha512-H88T9IySZW25anu5uqyaC1DaQre7ofM+joZtAaO2F8NBdFfupH0SZ4gKjgSFVcvtx/aAirqA9L9Clio2heYbZA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.2.2", - "@babel/types": "^7.2.2", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.4.4", "lodash": "^4.17.11" } }, @@ -176,9 +176,9 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.3.tgz", - "integrity": "sha512-hnoq5u96pLCfgjXuj8ZLX3QQ+6nAulS+zSgi6HulUwFbEruRAKwbGLU5OvXkE14L8XW6XsQEKsIDfgthKLRAyA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", "dev": true, "requires": { "lodash": "^4.17.11" @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.0.tgz", - "integrity": "sha512-PVwCVnWWAgnal+kJ+ZSAphzyl58XrFeSKSAJRiqg5QToTsjL+Xu1f9+RJ+d+Q0aPhPfBGaYfkox66k86thxNSg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/helper-simple-access": { @@ -220,12 +220,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", - "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", "dev": true, "requires": { - "@babel/types": "^7.4.0" + "@babel/types": "^7.4.4" } }, "@babel/helper-wrap-function": { @@ -241,14 +241,14 @@ } }, "@babel/helpers": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz", - "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", "dev": true, "requires": { - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0" + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/highlight": { @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", - "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -290,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.3.tgz", - "integrity": "sha512-xC//6DNSSHVjq8O2ge0dyYlhshsH4T7XdCVoxbi5HzLYWfsC5ooFlJjrXk8RcAT+hjHAK9UjBXdylzSoDK3t4g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -310,13 +310,13 @@ } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.0.tgz", - "integrity": "sha512-h/KjEZ3nK9wv1P1FSNb9G079jXrNYR0Ko+7XkOx85+gM24iZbPn0rh4vCftk+5QKY7y1uByFataBTmX7irEF1w==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", + "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", + "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" } }, @@ -366,9 +366,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.0.tgz", - "integrity": "sha512-EeaFdCeUULM+GPFEsf7pFcNSxM7hYjoj5fiYbyuiXobW4JhFnjAv9OWzNwHyHcKoPNpAfeRDuW6VyaXEDUBa7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -386,9 +386,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.0.tgz", - "integrity": "sha512-AWyt3k+fBXQqt2qb9r97tn3iBwFpiv9xdAiG+Gr2HpAZpuayvbL55yWrsV3MyHvXk/4vmSiedhDRl1YI2Iy5nQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -396,18 +396,18 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.3.tgz", - "integrity": "sha512-PUaIKyFUDtG6jF5DUJOfkBdwAS/kFFV3XFk7Nn0a6vR7ZT8jYw5cGtIlat77wcnd0C6ViGqo/wyNf4ZHytF/nQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.0", + "@babel/helper-define-map": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.0", - "@babel/helper-split-export-declaration": "^7.4.0", + "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" } }, @@ -421,22 +421,22 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.3.tgz", - "integrity": "sha512-rVTLLZpydDFDyN4qnXdzwoVpk1oaXHIvPEOkOLyr88o7oHxVc/LyrnDx+amuBWGOwUb7D1s/uLsKBNTx08htZg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.3.tgz", - "integrity": "sha512-9Arc2I0AGynzXRR/oPdSALv3k0rM38IMFyto7kOCwb5F9sLUt2Ykdo3V9yUPR+Bgr4kb6bVEyLkPEiBhzcTeoA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", + "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.3", + "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" } }, @@ -460,18 +460,18 @@ } }, "@babel/plugin-transform-for-of": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.3.tgz", - "integrity": "sha512-UselcZPwVWNSURnqcfpnxtMehrb8wjXYOimlYQPBnup/Zld426YzIhNEvuRsEWVHfESIECGrxoI6L5QqzuLH5Q==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-function-name": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.3.tgz", - "integrity": "sha512-uT5J/3qI/8vACBR9I1GlAuU/JqBtWdfCrynuOkrWG6nCDieZd5przB1vfP59FRHBZQ9DC2IUfqr/xKqzOD5x0A==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -507,23 +507,23 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.3.tgz", - "integrity": "sha512-sMP4JqOTbMJMimqsSZwYWsMjppD+KRyDIUVW91pd7td0dZKAvPmhCaxhOzkzLParKwgQc7bdL9UNv+rpJB0HfA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.4.3", + "@babel/helper-module-transforms": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-simple-access": "^7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.0.tgz", - "integrity": "sha512-gjPdHmqiNhVoBqus5qK60mWPp1CmYWp/tkh11mvb0rrys01HycEGD7NvvSoKXlWEfSM9TcL36CpsK8ElsADptQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.0", + "@babel/helper-hoist-variables": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0" } }, @@ -538,18 +538,18 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.2.tgz", - "integrity": "sha512-NsAuliSwkL3WO2dzWTOL1oZJHm0TM8ZY8ZSxk2ANyKkt5SQlToGA4pzctmq1BEjoacurdwZ3xp2dCQWJkME0gQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", + "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", "dev": true, "requires": { - "regexp-tree": "^0.1.0" + "regexp-tree": "^0.1.6" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.0.tgz", - "integrity": "sha512-6ZKNgMQmQmrEX/ncuCwnnw1yVGoaOW5KpxNhoWI7pCQdA0uZ0HqHGqenCUIENAnxRjy2WwNQ30gfGdIgqJXXqw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -566,12 +566,12 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.3.tgz", - "integrity": "sha512-ULJYC2Vnw96/zdotCZkMGr2QVfKpIT/4/K+xWWY0MbOJyMZuk660BGkr3bEKWQrrciwz6xpmft39nA4BF7hJuA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.4.0", + "@babel/helper-call-delegate": "^7.4.4", "@babel/helper-get-function-arity": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0" } @@ -586,12 +586,12 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.3.tgz", - "integrity": "sha512-kEzotPuOpv6/iSlHroCDydPkKYw7tiJGKlmYp6iJn4a6C/+b2FdttlJsLKYxolYHgotTJ5G5UY5h0qey5ka3+A==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", "dev": true, "requires": { - "regenerator-transform": "^0.13.4" + "regenerator-transform": "^0.14.0" } }, "@babel/plugin-transform-reserved-words": { @@ -632,9 +632,9 @@ } }, "@babel/plugin-transform-template-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz", - "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -651,104 +651,104 @@ } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.3.tgz", - "integrity": "sha512-lnSNgkVjL8EMtnE8eSS7t2ku8qvKH3eqNf/IwIfnSPUqzgqYmRwzdsQWv4mNQAN9Nuo6Gz1Y0a4CSmdpu1Pp6g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", + "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.3", + "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" } }, "@babel/preset-env": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.3.tgz", - "integrity": "sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", + "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.3", + "@babel/plugin-proposal-object-rest-spread": "^7.4.4", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-syntax-async-generators": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.0", + "@babel/plugin-transform-async-to-generator": "^7.4.4", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.0", - "@babel/plugin-transform-classes": "^7.4.3", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.4.4", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.3", - "@babel/plugin-transform-dotall-regex": "^7.4.3", + "@babel/plugin-transform-destructuring": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/plugin-transform-duplicate-keys": "^7.2.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.3", - "@babel/plugin-transform-function-name": "^7.4.3", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.3", - "@babel/plugin-transform-modules-systemjs": "^7.4.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-modules-systemjs": "^7.4.4", "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.2", - "@babel/plugin-transform-new-target": "^7.4.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.3", + "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.3", + "@babel/plugin-transform-regenerator": "^7.4.5", "@babel/plugin-transform-reserved-words": "^7.2.0", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.0", "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.3", - "@babel/types": "^7.4.0", - "browserslist": "^4.5.2", - "core-js-compat": "^3.0.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", "semver": "^5.5.0" } }, "@babel/template": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", - "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/traverse": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", - "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", + "@babel/generator": "^7.4.4", "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/types": "^7.4.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", - "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -840,9 +840,9 @@ } }, "@sinonjs/samsam": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", - "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", + "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", "dev": true, "requires": { "@sinonjs/commons": "^1.0.2", @@ -873,13 +873,13 @@ "dev": true }, "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "dev": true, "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" } }, "acorn": { @@ -935,9 +935,9 @@ "dev": true }, "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" @@ -990,13 +990,10 @@ "dev": true }, "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true }, "ansi-escapes": { "version": "3.2.0", @@ -1194,6 +1191,12 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1212,6 +1215,16 @@ "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", @@ -1247,6 +1260,18 @@ } } }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -1311,11 +1336,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -1361,29 +1387,21 @@ "dev": true }, "async-done": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", - "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.2", - "process-nextick-args": "^1.0.7", + "process-nextick-args": "^2.0.0", "stream-exhaust": "^1.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - } } }, "async-each": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", - "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, "async-limiter": { @@ -1715,15 +1733,15 @@ } }, "babel-loader": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz", - "integrity": "sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", "dev": true, "requires": { "find-cache-dir": "^2.0.0", "loader-utils": "^1.0.2", "mkdirp": "^0.5.1", - "util.promisify": "^1.0.0" + "pify": "^4.0.1" } }, "babel-messages": { @@ -2568,9 +2586,9 @@ "dev": true }, "bail": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz", + "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==", "dev": true }, "balanced-match": { @@ -2729,9 +2747,9 @@ "dev": true }, "bluebird": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", - "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", "dev": true }, "bn.js": { @@ -2753,27 +2771,27 @@ } }, "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { - "bytes": "3.0.0", + "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" }, "dependencies": { "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "debug": { @@ -2785,13 +2803,17 @@ "ms": "2.0.0" } }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } }, "ms": { @@ -2800,17 +2822,29 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true } } }, @@ -2954,14 +2988,14 @@ } }, "browserslist": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.4.tgz", - "integrity": "sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000955", - "electron-to-chromium": "^1.3.122", - "node-releases": "^1.1.13" + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" } }, "browserstack": { @@ -2974,9 +3008,9 @@ } }, "browserstack-local": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.3.7.tgz", - "integrity": "sha512-ilZlmiy7XYJxsztYan7XueHVr3Ix9EVh/mCiYN1G53wRPEW/hg1KMsseM6UExzVbexEqFEfwjkBLeFlSqxh+bQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", + "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", @@ -3001,14 +3035,13 @@ } }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", "dev": true, "requires": { "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "ieee754": "^1.1.4" } }, "buffer-alloc": { @@ -3132,7 +3165,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3174,9 +3207,9 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { @@ -3198,9 +3231,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000957", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz", - "integrity": "sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ==", + "version": "1.0.30000975", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", + "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", "dev": true }, "caseless": { @@ -3210,9 +3243,9 @@ "dev": true }, "ccount": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", + "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==", "dev": true }, "center-align": { @@ -3251,27 +3284,27 @@ } }, "character-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", + "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", "dev": true }, "character-entities-html4": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.3.tgz", + "integrity": "sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==", "dev": true }, "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", + "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", "dev": true }, "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", + "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", "dev": true }, "chardet": { @@ -3293,9 +3326,9 @@ "dev": true }, "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -3367,14 +3400,31 @@ "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "clone": { @@ -3405,9 +3455,9 @@ "dev": true }, "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -3428,9 +3478,9 @@ "dev": true }, "collapse-white-space": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.5.tgz", + "integrity": "sha512-703bOOmytCYAX9cXYqoikYIx6twmFCXsnzRQheBcTG3nzKYBR4P/+wkYeH+Mvj7qUz8zZDtdyzbxfnEi/kYzRQ==", "dev": true }, "collection-map": { @@ -3491,27 +3541,24 @@ } }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, "comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz", + "integrity": "sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ==", + "dev": true }, "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, "commondir": { @@ -3527,9 +3574,9 @@ "dev": true }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, "component-inherit": { @@ -3597,14 +3644,14 @@ } }, "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "requires": { "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", "utils-merge": "1.0.1" }, "dependencies": { @@ -3711,40 +3758,33 @@ } }, "core-js": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", - "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" }, "core-js-compat": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.1.tgz", - "integrity": "sha512-2pC3e+Ht/1/gD7Sim/sqzvRplMiRnFQVlPpDVaHtY9l7zZP7knamr3VRD6NyGfHd84MrDC0tAM9ulNxYMW0T3g==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", + "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", "dev": true, "requires": { - "browserslist": "^4.5.4", - "core-js": "3.0.1", - "core-js-pure": "3.0.1", - "semver": "^6.0.0" + "browserslist": "^4.6.2", + "core-js-pure": "3.1.4", + "semver": "^6.1.1" }, "dependencies": { - "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", - "dev": true - }, "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true } } }, "core-js-pure": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.0.1.tgz", - "integrity": "sha512-mSxeQ6IghKW3MoyF4cz19GJ1cMm7761ON+WObSyLfTu/Jn3x7w4NwNFnrZxgl4MTSvYYepVLNuRtlB4loMwJ5g==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.1.4.tgz", + "integrity": "sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==", "dev": true }, "core-util-is": { @@ -3754,9 +3794,9 @@ "dev": true }, "coveralls": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.3.tgz", - "integrity": "sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", + "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -3774,18 +3814,6 @@ "dev": true, "requires": { "buffer": "^5.1.0" - }, - "dependencies": { - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - } } }, "crc32-stream": { @@ -3836,12 +3864,14 @@ } }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -3921,12 +3951,13 @@ "dev": true }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "dashdash": { @@ -4161,9 +4192,9 @@ "dev": true }, "detab": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.1.tgz", - "integrity": "sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.2.tgz", + "integrity": "sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ==", "dev": true, "requires": { "repeat-string": "^1.5.4" @@ -4324,12 +4355,62 @@ "yargs": "^9.0.1" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -4339,12 +4420,36 @@ "locate-path": "^2.0.0" } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -4375,6 +4480,32 @@ "path-exists": "^3.0.0" } }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -4442,24 +4573,17 @@ "path-type": "^2.0.0" } }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true }, "yargs": { "version": "9.0.1", @@ -4493,6 +4617,15 @@ } } } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -4580,15 +4713,15 @@ "dev": true }, "ejs": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", - "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", + "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", "dev": true }, "electron-to-chromium": { - "version": "1.3.124", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", - "integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==", + "version": "1.3.164", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", + "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", "dev": true }, "elliptic": { @@ -4607,9 +4740,9 @@ } }, "emoji-regex": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", - "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "emojis-list": { @@ -4636,7 +4769,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4650,7 +4783,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4666,7 +4799,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4683,10 +4816,16 @@ "yeast": "0.1.2" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4785,9 +4924,9 @@ } }, "es5-ext": { - "version": "0.10.49", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz", - "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==", + "version": "0.10.50", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", + "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -4827,9 +4966,9 @@ } }, "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true }, "es6-promisify": { @@ -4865,14 +5004,14 @@ } }, "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, "requires": { "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.1" } }, @@ -4989,6 +5128,17 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -5052,9 +5202,9 @@ } }, "eslint-module-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", - "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", + "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5131,21 +5281,22 @@ } }, "eslint-plugin-import": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", - "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", + "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", "dev": true, "requires": { + "array-includes": "^3.0.3", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.3.0", + "eslint-module-utils": "^2.4.0", "has": "^1.0.3", "lodash": "^4.17.11", "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.9.0" + "resolve": "^1.11.0" }, "dependencies": { "debug": { @@ -5377,7 +5528,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5399,9 +5550,9 @@ } }, "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, "events": { @@ -5435,19 +5586,6 @@ "strip-eof": "^1.0.0" }, "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -5456,16 +5594,6 @@ "requires": { "pump": "^3.0.0" } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } } } }, @@ -5624,40 +5752,6 @@ "vary": "~1.1.2" }, "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, "cookie": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", @@ -5673,21 +5767,6 @@ "ms": "2.0.0" } }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -5701,39 +5780,12 @@ "toidentifier": "1.0.0" } }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", - "dev": true - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -5746,24 +5798,6 @@ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -5793,39 +5827,11 @@ } } }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } } } }, @@ -6057,17 +6063,17 @@ } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", + "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", "unpipe": "~1.0.0" }, "dependencies": { @@ -6121,9 +6127,9 @@ } }, "fined": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", - "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", "dev": true, "requires": { "expand-tilde": "^2.0.2", @@ -6139,6 +6145,23 @@ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", @@ -6165,7 +6188,7 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -6359,40 +6382,36 @@ "dev": true }, "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" }, "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6402,14 +6421,12 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -6418,71 +6435,61 @@ }, "chownr": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true, "optional": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.1.1", + "bundled": true, "dev": true, "optional": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6491,15 +6498,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6515,8 +6520,7 @@ }, "glob": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6530,15 +6534,13 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6547,8 +6549,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6557,8 +6558,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6568,21 +6568,18 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "dev": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -6590,15 +6587,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -6606,14 +6601,12 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "dev": true }, "minipass": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -6622,8 +6615,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6632,36 +6624,32 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dev": true, "requires": { "minimist": "0.0.8" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "bundled": true, "dev": true, "optional": true }, "needle": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", - "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", + "version": "2.3.0", + "bundled": true, "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", + "debug": "^4.1.0", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", - "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", + "version": "0.12.0", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6679,8 +6667,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6689,16 +6676,14 @@ } }, "npm-bundled": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", - "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", + "version": "1.0.6", + "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.2.0.tgz", - "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", + "version": "1.4.1", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6708,8 +6693,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6721,21 +6705,18 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "bundled": true, "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "requires": { "wrappy": "1" @@ -6743,22 +6724,19 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6768,22 +6746,19 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6795,8 +6770,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } @@ -6804,8 +6778,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6820,8 +6793,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6830,49 +6802,42 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "bundled": true, "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "dev": true, "optional": true }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.7.0", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -6882,8 +6847,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6892,8 +6856,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -6901,15 +6864,13 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6924,15 +6885,13 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6941,22 +6900,20 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true }, "yallist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "bundled": true, "dev": true } } }, "fun-hooks": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.2.tgz", - "integrity": "sha512-Bbhqg3zj/joiHsmU9z/DBPofMN8yN4P7m2cE4sqZqaL+C6YcAXKjwa7Cu8rUs3roBiAhgWwQOAALZZodpmBglw==" + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", + "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" }, "function-bind": { "version": "1.1.1", @@ -6980,9 +6937,9 @@ } }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-func-name": { @@ -7051,12 +7008,20 @@ "dev": true, "requires": { "emoji-regex": ">=6.0.0 <=6.1.1" + }, + "dependencies": { + "emoji-regex": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "dev": true + } } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7181,9 +7146,9 @@ } }, "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "globals-docs": { @@ -7264,23 +7229,43 @@ "dev": true }, "gulp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", - "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, "requires": { - "glob-watcher": "^5.0.0", - "gulp-cli": "^2.0.0", - "undertaker": "^1.0.0", + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", "vinyl-fs": "^3.0.0" }, "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -7291,10 +7276,16 @@ "pinkie-promise": "^2.0.0" } }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, "gulp-cli": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.1.0.tgz", - "integrity": "sha512-txzgdFVlEPShBZus6JJyGyKJoBVDq6Do0ZQgIgx5RAsmhNVTDjymmOxpQvo3c20m66FldilS68ZXj2Q9w5dKbA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -7317,6 +7308,30 @@ "yargs": "^7.1.0" } }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -7395,6 +7410,23 @@ "read-pkg": "^1.0.0" } }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -7410,6 +7442,12 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", @@ -7624,7 +7662,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7641,7 +7679,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -8062,9 +8100,9 @@ } }, "handlebars": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", - "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -8253,15 +8291,15 @@ } }, "hast-util-is-element": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.2.tgz", - "integrity": "sha512-4MEtyofNi3ZunPFrp9NpTQdNPN24xvLX3M+Lr/RGgPX6TLi+wR4/DqeoyQ7lwWcfUp4aevdt4RR0r7ZQPFbHxw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.3.tgz", + "integrity": "sha512-C62CVn7jbjp89yOhhy7vrkSaB7Vk906Gtcw/Ihd+Iufnq+2pwOZjdPmpzpKLWJXPJBMDX3wXg4FqmdOayPcewA==", "dev": true }, "hast-util-sanitize": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.0.tgz", - "integrity": "sha512-rQeetoD08jHmDOUYN6h9vTuE0hQN4wymhtkQZ6whHtcjaLpjw5RYAbcdxx9cMgMWERDsSs79UpqHuBLlUHKeOw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.1.tgz", + "integrity": "sha512-AIeKHuHx0Wk45nSkGVa2/ujQYTksnDl8gmmKo/mwQi7ag7IBZ8cM3nJ2G86SajbjGP/HRpud6kMkPtcM2i0Tlw==", "dev": true, "requires": { "xtend": "^4.0.1" @@ -8284,24 +8322,32 @@ "stringify-entities": "^1.0.1", "unist-util-is": "^2.0.0", "xtend": "^4.0.1" + }, + "dependencies": { + "unist-util-is": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.3.tgz", + "integrity": "sha512-4WbQX2iwfr/+PfM4U3zd2VNXY+dWtZsN1fLnWEi2QQXA4qyDYAZcDMfXUX0Cu6XZUHHAO9q4nyxxLT4Awk1qUA==", + "dev": true + } } }, "hast-util-whitespace": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.2.tgz", - "integrity": "sha512-4JT8B0HKPHBMFZdDQzexjxwhKx9TrpV/+uelvmqlPu8RqqDrnNIEHDtDZCmgE+4YmcFAtKVPLmnY3dQGRaN53A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.3.tgz", + "integrity": "sha512-AlkYiLTTwPOyxZ8axq2/bCwRUPjIPBfrHkXuCR92B38b3lSdU22R5F/Z4DL6a2kxWpekWq1w6Nj48tWat6GeRA==", "dev": true }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "highlight.js": { - "version": "9.15.6", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.6.tgz", - "integrity": "sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==", + "version": "9.15.8", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", + "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA==", "dev": true }, "hmac-drbg": { @@ -8347,9 +8393,9 @@ "dev": true }, "html-void-elements": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.3.tgz", - "integrity": "sha512-SaGhCDPXJVNrQyKMtKy24q6IMdXg5FCPN3z+xizxw9l+oXQw5fOoaj/ERU5KqWhSYhXtW5bWthlDbTDLBhJQrA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.4.tgz", + "integrity": "sha512-yMk3naGPLrfvUV9TdDbuYXngh/TpHbA6TrOw3HL9kS8yhwx7i309BReNg7CbAJXGE+UMJ6je5OqJ7lC63o6YuQ==", "dev": true }, "http-cache-semantics": { @@ -8360,7 +8406,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8368,20 +8414,12 @@ "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" - }, - "dependencies": { - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - } } }, "http-parser-js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", "dev": true }, "http-proxy": { @@ -8531,22 +8569,6 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -8584,9 +8606,9 @@ } }, "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "ipaddr.js": { @@ -8626,9 +8648,9 @@ } }, "is-alphabetical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", + "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", "dev": true }, "is-alphanumeric": { @@ -8638,15 +8660,21 @@ "dev": true }, "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", + "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8701,9 +8729,9 @@ "dev": true }, "is-decimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", + "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", "dev": true }, "is-descriptor": { @@ -8768,13 +8796,16 @@ } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true }, "is-glob": { "version": "4.0.1", @@ -8786,9 +8817,9 @@ } }, "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", + "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", "dev": true }, "is-negated-glob": { @@ -8944,9 +8975,9 @@ "dev": true }, "is-whitespace-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz", + "integrity": "sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==", "dev": true }, "is-windows": { @@ -8956,9 +8987,9 @@ "dev": true }, "is-word-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", - "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.3.tgz", + "integrity": "sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==", "dev": true }, "is-wsl": { @@ -9324,6 +9355,12 @@ "integrity": "sha1-6l7+QLg2kLmGZ2FKc5L8YOhCwN0=", "dev": true }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -9362,7 +9399,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9396,9 +9433,9 @@ }, "dependencies": { "mime": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", - "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, "rimraf": { @@ -9639,12 +9676,12 @@ } }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "lcov-parse": { @@ -9864,6 +9901,12 @@ "lodash._objecttypes": "~2.4.1" } }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, "lodash.defaults": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", @@ -9987,7 +10030,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -10000,7 +10043,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "debug": { @@ -10037,9 +10080,9 @@ "dev": true }, "longest-streak": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.3.tgz", + "integrity": "sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==", "dev": true }, "loose-envify": { @@ -10120,6 +10163,15 @@ "kind-of": "^6.0.2" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -10148,15 +10200,15 @@ } }, "markdown-escapes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.3.tgz", + "integrity": "sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==", "dev": true }, "markdown-table": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", - "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", "dev": true }, "matchdep": { @@ -10212,18 +10264,18 @@ } }, "mdast-util-compact": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", - "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", + "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", "dev": true, "requires": { "unist-util-visit": "^1.1.0" } }, "mdast-util-definitions": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz", - "integrity": "sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz", + "integrity": "sha512-HfUArPog1j4Z78Xlzy9Q4aHLnrF/7fb57cooTHypyGoe2XFNbcx/kWZDoOz+ra8CkUzvg3+VHV434yqEd1DRmA==", "dev": true, "requires": { "unist-util-visit": "^1.0.0" @@ -10258,9 +10310,9 @@ } }, "mdast-util-to-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz", - "integrity": "sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.6.tgz", + "integrity": "sha512-868pp48gUPmZIhfKrLbaDneuzGiw3OTDjHc5M1kAepR2CWBJ+HpEsm252K4aXdiP5coVZaJPOqGtVU6Po8xnXg==", "dev": true }, "mdast-util-toc": { @@ -10275,6 +10327,12 @@ "unist-util-visit": "^1.1.0" }, "dependencies": { + "emoji-regex": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz", + "integrity": "sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=", + "dev": true + }, "github-slugger": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", @@ -10283,6 +10341,12 @@ "requires": { "emoji-regex": ">=6.0.0 <=6.1.1" } + }, + "unist-util-is": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.3.tgz", + "integrity": "sha512-4WbQX2iwfr/+PfM4U3zd2VNXY+dWtZsN1fLnWEi2QQXA4qyDYAZcDMfXUX0Cu6XZUHHAO9q4nyxxLT4Awk1qUA==", + "dev": true } } }, @@ -10299,12 +10363,22 @@ "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + } } }, "memoizee": { @@ -10333,6 +10407,12 @@ "readable-stream": "^2.0.1" } }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -10500,24 +10580,24 @@ "dev": true }, "mime-db": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", - "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", "dev": true }, "mime-types": { - "version": "2.1.22", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", - "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "dev": true, "requires": { - "mime-db": "~1.38.0" + "mime-db": "1.40.0" } }, "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "mimic-response": { @@ -10549,7 +10629,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -10585,7 +10665,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10610,6 +10690,12 @@ "supports-color": "5.4.0" }, "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -10639,6 +10725,12 @@ "path-is-absolute": "^1.0.0" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -10720,9 +10812,9 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "multipipe": { @@ -10782,9 +10874,9 @@ "dev": true }, "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, @@ -10820,15 +10912,15 @@ "dev": true }, "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", "dev": true }, "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, "next-tick": { @@ -10844,15 +10936,15 @@ "dev": true }, "nise": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", - "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", + "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", "dev": true, "requires": { "@sinonjs/formatio": "^3.1.0", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", - "lolex": "^2.3.2", + "lolex": "^4.1.0", "path-to-regexp": "^1.7.0" }, "dependencies": { @@ -10867,17 +10959,27 @@ } }, "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", + "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", "dev": true } } }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, "node-libs-browser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", - "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, "requires": { "assert": "^1.1.1", @@ -10890,7 +10992,7 @@ "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", + "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", @@ -10902,21 +11004,41 @@ "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.11.0", - "vm-browserify": "0.0.4" + "vm-browserify": "^1.0.1" }, "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } } } }, "node-releases": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.14.tgz", - "integrity": "sha512-d58EpVZRhQE60kWiWUaaPlK9dyC4zg3ZoMcHcky2d4hDksyQj0rUozwInOl0C66mBsqo01Tuns8AvxnL5S7PKg==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10976,6 +11098,23 @@ "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", "dev": true }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -11085,6 +11224,18 @@ "isobject": "^3.0.0" } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11170,6 +11321,14 @@ "dev": true, "requires": { "mimic-fn": "^1.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + } } }, "opener": { @@ -11199,7 +11358,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11247,31 +11406,14 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - } + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, "os-tmpdir": { @@ -11286,6 +11428,12 @@ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -11361,21 +11509,144 @@ } }, "parse-domain": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.1.7.tgz", - "integrity": "sha512-yb0VWRwDCe96ML49b3xg+4wScbocpIrFSAdkml8eKq/deH3FiFPBpsC6RTC9ZUtnDhInmXPfNIHsN/v62+TAMA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", + "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", "dev": true, "requires": { "chai": "^4.2.0", "got": "^8.3.2", "mkdirp": "^0.5.1", - "mocha": "^5.2.0" + "mocha": "^6.1.4", + "npm-run-all": "^4.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mocha": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", + "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + } + } } }, "parse-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz", - "integrity": "sha512-NBWYLQm1KSoDKk7GAHyioLTvCZ5QjdH/ASBBQTD3iLiAWJXS5bg1jEWI8nIJ+vgVvsceBVBcDGRWSo0KVQBvvg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", "dev": true, "requires": { "character-entities": "^1.0.0", @@ -11498,9 +11769,9 @@ } }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "pascalcase": { @@ -11510,9 +11781,9 @@ "dev": true }, "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "path-dirname": { @@ -11646,6 +11917,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pidtree": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -11686,6 +11963,17 @@ "arr-diff": "^4.0.0", "arr-union": "^3.1.0", "extend-shallow": "^3.0.2" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + } } }, "pluralize": { @@ -11792,9 +12080,9 @@ "dev": true }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", + "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", "dev": true }, "public-encrypt": { @@ -11812,9 +12100,9 @@ } }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -11830,6 +12118,18 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "punycode": { @@ -11923,9 +12223,9 @@ } }, "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, "raw-body": { @@ -12064,9 +12364,9 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", - "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -12078,9 +12378,9 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", - "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", + "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", "dev": true, "requires": { "private": "^0.1.6" @@ -12106,9 +12406,9 @@ } }, "regexp-tree": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.5.tgz", - "integrity": "sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", + "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", "dev": true }, "regexpp": { @@ -12201,18 +12501,18 @@ } }, "remark-reference-links": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.3.tgz", - "integrity": "sha512-Q9d7JaK5r0JDBo3TInfrodBuI3xulI8htCr8jlX+0oXosF3GaebJbo5y228VYFoV6xJ+syDukkUGMKNlwSJWjQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.4.tgz", + "integrity": "sha512-+2X8hwSQqxG4tvjYZNrTcEC+bXp8shQvwRGG6J/rnFTvBoU4G0BBviZoqKGZizLh/DG+0gSYhiDDWCqyxXW1iQ==", "dev": true, "requires": { "unist-util-visit": "^1.0.0" } }, "remark-slug": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.1.tgz", - "integrity": "sha512-r591rdoDPJkSSAVvEaTVUkqbMp7c7AyZfif14V0Dp66GQkOHzaPAS6wyhawSbqpS0ZdTnfJS+TltFoxzi6bdIA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.2.tgz", + "integrity": "sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==", "dev": true, "requires": { "github-slugger": "^1.0.0", @@ -12393,9 +12693,9 @@ "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "require-uncached": { @@ -12415,9 +12715,9 @@ "dev": true }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12480,9 +12780,9 @@ "dev": true }, "rfdc": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", "dev": true }, "rgb2hex": { @@ -12680,16 +12980,81 @@ } }, "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + } + } }, "set-blocking": { "version": "2.0.0", @@ -12757,6 +13122,18 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", @@ -12816,14 +13193,6 @@ "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } } }, "snapdragon": { @@ -12951,7 +13320,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -12965,7 +13334,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -12988,7 +13357,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13007,10 +13376,16 @@ "to-array": "0.1.4" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13026,7 +13401,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13035,10 +13410,16 @@ "isarray": "2.0.1" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13108,13 +13489,10 @@ "dev": true }, "space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "dev": true, - "requires": { - "trim": "0.0.1" - } + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.4.tgz", + "integrity": "sha512-UyhMSmeIqZrQn2UdjYpxEkwY9JUrn8pP+7L4f91zRzOQuI8MF1FGLfYU9DKCYeLdo7LXMxwrX5zKFy7eeeVHuA==", + "dev": true }, "sparkles": { "version": "1.0.1", @@ -13156,7 +13534,7 @@ }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13202,9 +13580,9 @@ "dev": true }, "state-toggle": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", + "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==", "dev": true }, "static-extend": { @@ -13229,9 +13607,9 @@ } }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "stealthy-require": { @@ -13290,7 +13668,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13368,14 +13746,41 @@ "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.padend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", + "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" } }, "string_decoder": { @@ -13481,39 +13886,6 @@ "lodash": "^4.17.4", "slice-ansi": "1.0.0", "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "tapable": { @@ -13788,9 +14160,9 @@ "dev": true }, "trim-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.1.tgz", - "integrity": "sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-1.1.2.tgz", + "integrity": "sha512-3GOuyNeTqk3FAqc3jOJtw7FTjYl94XBR5aD9QnDbK/T4CA9sW/J0l9RoaRPE9wyPP7NF331qnHnvJFBJ+IDkmQ==", "dev": true }, "trim-newlines": { @@ -13806,15 +14178,15 @@ "dev": true }, "trim-trailing-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz", + "integrity": "sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==", "dev": true }, "trough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.4.tgz", + "integrity": "sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==", "dev": true }, "tryer": { @@ -13844,6 +14216,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", + "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -13860,13 +14238,13 @@ "dev": true }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "~2.1.24" } }, "typedarray": { @@ -13876,21 +14254,15 @@ "dev": true }, "uglify-js": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.4.tgz", - "integrity": "sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, "requires": { "commander": "~2.20.0", "source-map": "~0.6.1" }, "dependencies": { - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -13944,12 +14316,6 @@ "yargs": "~3.10.0" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", @@ -14006,9 +14372,9 @@ "dev": true }, "unherit": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", - "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", + "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -14103,36 +14469,36 @@ } }, "unist-builder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.3.tgz", - "integrity": "sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.4.tgz", + "integrity": "sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg==", "dev": true, "requires": { "object-assign": "^4.1.0" } }, "unist-util-generated": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.3.tgz", - "integrity": "sha512-qlPeDqnQnd84KIqwphzOR+l02cxjDzvEYEBl84EjmKRrX4eUmjyAo8xJv1SCDhJqNjyHRnBMZWNKAiBtXE6hBg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.4.tgz", + "integrity": "sha512-SA7Sys3h3X4AlVnxHdvN/qYdr4R38HzihoEVY2Q2BZu8NHWDnw5OGcC/tXWjQfd4iG+M6qRFNIRGqJmp2ez4Ww==", "dev": true }, "unist-util-is": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", - "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", "dev": true }, "unist-util-position": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.2.tgz", - "integrity": "sha512-npmFu92l/+b1Ao6uGP4I1WFz9hsKv7qleZ4aliw6x0RVu6A9A3tAf57NMpFfzQ02jxRtJZuRn+C8xWT7GWnH0g==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.3.tgz", + "integrity": "sha512-28EpCBYFvnMeq9y/4w6pbnFmCUfzlsc41NJui5c51hOFjBA1fejcwc+5W4z2+0ECVbScG3dURS3JTVqwenzqZw==", "dev": true }, "unist-util-remove-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", - "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", + "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", "dev": true, "requires": { "unist-util-visit": "^1.1.0" @@ -14145,21 +14511,21 @@ "dev": true }, "unist-util-visit": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", - "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", "dev": true, "requires": { "unist-util-visit-parents": "^2.0.0" } }, "unist-util-visit-parents": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", - "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", "dev": true, "requires": { - "unist-util-is": "^2.1.2" + "unist-util-is": "^3.0.0" } }, "unpipe": { @@ -14254,12 +14620,12 @@ "dev": true }, "url-parse": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", - "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, "requires": { - "querystringify": "^2.0.0", + "querystringify": "^2.1.1", "requires-port": "^1.0.0" }, "dependencies": { @@ -14303,7 +14669,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14311,12 +14677,16 @@ } }, "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", + "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" } }, "util-deprecate": { @@ -14325,16 +14695,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -14348,9 +14708,9 @@ "dev": true }, "v8flags": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", - "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -14402,9 +14762,9 @@ } }, "vfile-location": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz", - "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.5.tgz", + "integrity": "sha512-Pa1ey0OzYBkLPxPZI3d9E+S4BmvfVwNAAXrrqGbwTVXWaX2p9kM1zZ+n35UtVM06shmWKH4RPRN8KI80qE3wNQ==", "dev": true }, "vfile-message": { @@ -14435,6 +14795,26 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -14447,15 +14827,15 @@ } }, "vfile-sort": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.0.tgz", - "integrity": "sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.1.tgz", + "integrity": "sha512-5dt7xEhC44h0uRQKhbM2JAe0z/naHphIZlMOygtMBM9Nn0pZdaX5fshhwWit9wvsuP8t/wp43nTDRRErO1WK8g==", "dev": true }, "vfile-statistics": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.2.tgz", - "integrity": "sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.3.tgz", + "integrity": "sha512-CstaK/ebTz1W3Qp41Bt9Lj/2DmumFsCwC2sKahDNSPh0mPh7/UyMLCoU8ZBX34CRU0d61B4W41yIFsV0NKMZeA==", "dev": true }, "vinyl": { @@ -14533,13 +14913,10 @@ } }, "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true }, "void-elements": { "version": "2.0.1", @@ -14653,12 +15030,6 @@ "wgxpath": "~1.0.0" }, "dependencies": { - "ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", - "dev": true - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -14724,12 +15095,6 @@ "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, "async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", @@ -14739,6 +15104,62 @@ "lodash": "^4.17.11" } }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -14754,18 +15175,33 @@ "locate-path": "^2.0.0" } }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -14778,6 +15214,15 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -14800,6 +15245,32 @@ "path-exists": "^3.0.0" } }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -14869,24 +15340,11 @@ "read-pkg": "^2.0.0" } }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true }, "supports-color": { "version": "4.5.0", @@ -14897,6 +15355,12 @@ "has-flag": "^2.0.0" } }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -14917,6 +15381,15 @@ "y18n": "^3.2.1", "yargs-parser": "^7.0.0" } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -14947,10 +15420,10 @@ "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "ejs": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", + "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==", "dev": true }, "ws": { @@ -14993,7 +15466,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15007,9 +15480,9 @@ }, "dependencies": { "mime": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", - "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true } } @@ -15125,6 +15598,17 @@ "pako": "~0.2.0" } }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", @@ -15335,12 +15819,6 @@ "object-assign": "^4.0.1" } }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, "memory-fs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", @@ -15424,6 +15902,12 @@ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -15509,6 +15993,15 @@ "replace-ext": "0.0.1" } }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", @@ -15551,12 +16044,6 @@ "webpack-core": "~0.6.9" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", @@ -15578,12 +16065,13 @@ } }, "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", + "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, @@ -15614,6 +16102,21 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -15628,6 +16131,28 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "wrappy": { @@ -15675,9 +16200,9 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { @@ -15693,12 +16218,68 @@ "dev": true }, "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, "yeast": { diff --git a/package.json b/package.json index 11d5ee5901f..0a68cb6d5d9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0-pre", + "version": "2.20.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 18282265659eab5fdc86caf5d0e3a506462a24be Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 18 Jun 2019 15:58:57 -0400 Subject: [PATCH 027/436] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c03303a050..1d224cebc76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0", + "version": "2.21.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0a68cb6d5d9..a4e2985e1bd 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.20.0", + "version": "2.21.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 52cc1353fb07da4fb3ce0d86b64a43506309ca9a Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 18 Jun 2019 13:12:06 -0700 Subject: [PATCH 028/436] always secure (#3922) changed serevr end-point to HTTPS changed user-sync end-point to HTTPS changed imp.secure to 1 hard-coded Also corrected test case --- modules/pubmaticBidAdapter.js | 6 +++--- test/spec/modules/pubmaticBidAdapter_spec.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 1f9ea06cad2..245ca3e60c9 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -5,8 +5,8 @@ import {config} from '../src/config'; const BIDDER_CODE = 'pubmatic'; const LOG_WARN_PREFIX = 'PubMatic: '; -const ENDPOINT = '//hbopenbid.pubmatic.com/translator?source=prebid-client'; -const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; +const ENDPOINT = 'https://hbopenbid.pubmatic.com/translator?source=prebid-client'; +const USYNCURL = 'https://ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const DEFAULT_CURRENCY = 'USD'; const AUCTION_TYPE = 1; const PUBMATIC_DIGITRUST_KEY = 'nFIn8aLzbd'; @@ -513,7 +513,7 @@ function _createImpressionObject(bid, conf) { id: bid.bidId, tagid: bid.params.adUnit || undefined, bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), - secure: window.location.protocol === 'https:' ? 1 : 0, + secure: 1, ext: { pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) }, diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 6126c0f9fd8..289e0f461ec 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -695,7 +695,7 @@ describe('PubMatic adapter', function () { it('Endpoint checking', function () { let request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); + expect(request.url).to.equal('https://hbopenbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); }); From f8fa4a2ea1047fc37012a7f9fbeb1b39c107e13c Mon Sep 17 00:00:00 2001 From: susyt Date: Thu, 20 Jun 2019 08:15:40 -0700 Subject: [PATCH 029/436] GumGum: adds tradedesk id param (#3896) * adds tradedesk id param * adds more tests * removes only from test spec * linting fix * updates one of the unit tests --- modules/gumgumBidAdapter.js | 10 +++- test/spec/modules/gumgumBidAdapter_spec.js | 54 ++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 8c2b6415505..496941e3c1f 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -75,6 +75,14 @@ function getWrapperCode(wrapper, data) { return wrapper.replace('AD_JSON', window.btoa(JSON.stringify(data))) } +function _getTradeDeskIDParam(bidRequest) { + const unifiedIdObj = {}; + if (bidRequest.userId && bidRequest.userId.tdid) { + unifiedIdObj.tdid = bidRequest.userId.tdid; + } + return unifiedIdObj; +} + // TODO: use getConfig() function _getDigiTrustQueryParams() { function getDigiTrustId () { @@ -170,7 +178,7 @@ function buildRequests (validBidRequests, bidderRequest) { sizes: bidRequest.sizes, url: BID_ENDPOINT, method: 'GET', - data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams()) + data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) }) }); return bids; diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index c067f50fa56..a7a588afd13 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -80,6 +80,35 @@ describe('gumgumAdapter', function () { expect(request.method).to.equal('GET'); expect(request.id).to.equal('30b31c1838de1e'); }); + it('should correctly set the request paramters depending on params field', function () { + const request = Object.assign({}, bidRequests[0]); + delete request.params; + request.params = { + 'inScreen': '10433394', + 'bidfloor': 0.05 + }; + const bidRequest = spec.buildRequests([request])[0]; + expect(bidRequest.data.pi).to.equal(2); + expect(bidRequest.data).to.include.any.keys('t'); + expect(bidRequest.data).to.include.any.keys('fp'); + }); + it('should correctly set the request paramters depending on params field', function () { + const request = Object.assign({}, bidRequests[0]); + delete request.params; + request.params = { + 'ICV': '10433395' + }; + const bidRequest = spec.buildRequests([request])[0]; + expect(bidRequest.data.pi).to.equal(5); + expect(bidRequest.data).to.include.any.keys('ni'); + }); + it('should not add additional parameters depending on params field', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data).to.not.include.any.keys('ni'); + expect(request.data).to.not.include.any.keys('t'); + expect(request.data).to.not.include.any.keys('eAdBuyId'); + expect(request.data).to.not.include.any.keys('adBuyId'); + }); it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; @@ -93,6 +122,31 @@ describe('gumgumAdapter', function () { const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; expect(bidRequest.data).to.not.include.any.keys('gdprConsent') }); + it('should add a tdid parameter if request contains unified id from TradeDesk', function () { + const unifiedId = { + 'userId': { + 'tdid': 'tradedesk-id' + } + } + const request = Object.assign(unifiedId, bidRequests[0]); + const bidRequest = spec.buildRequests([request])[0]; + expect(bidRequest.data.tdid).to.eq(unifiedId.userId.tdid); + }); + it('should not add a tdid parameter if unified id is not found', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data).to.not.include.any.keys('tdid'); + }); + it('should send ns parameter if browser contains navigator.connection property', function () { + const bidRequest = spec.buildRequests(bidRequests)[0]; + const connection = window.navigator && window.navigator.connection; + if (connection) { + const downlink = connection.downlink || connection.bandwidth; + expect(bidRequest.data).to.include.any.keys('ns'); + expect(bidRequest.data.ns).to.eq(Math.round(downlink * 1024)); + } else { + expect(bidRequest.data).to.not.include.any.keys('ns'); + } + }); }) describe('interpretResponse', function () { From a248f976c203fc2f3fb4deee1e8836e3c2a2f1e8 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Fri, 21 Jun 2019 17:23:57 -0400 Subject: [PATCH 030/436] Digitrust support in PBS bid adapter and Rubicon bid adapter (#3935) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * - Get digitrust data from bid request - Send UnifiedID and PubCommon data to OpenRTB * - Replace lodash with Prebid util functions - Updated pubcommon id location when sending to OpenRTB * Remove pref property when sending DigiTrust to OpenRTB * Updated tests to check new user external id locations in request * Remove use of array find from unit test --- modules/prebidServerBidAdapter/index.js | 64 ++++++----- modules/rubiconBidAdapter.js | 107 +++++++++++------- src/utils.js | 17 +++ .../modules/prebidServerBidAdapter_spec.js | 58 +++++----- 4 files changed, 146 insertions(+), 100 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 586d78ed2ca..028f02d9662 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -232,20 +232,24 @@ function doClientSideSyncs(bidders) { }); } -function _getDigiTrustQueryParams() { - function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); +function _getDigiTrustQueryParams(bidRequest = {}) { + function getDigiTrustId(bidRequest) { + const bidRequestDigitrust = utils.deepAccess(bidRequest, 'bids.0.userId.digitrustid.data'); + if (bidRequestDigitrust) { + return bidRequestDigitrust; + } + + const digiTrustUser = config.getConfig('digiTrustId'); return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; } - let digiTrustId = getDigiTrustId(); + let digiTrustId = getDigiTrustId(bidRequest); // Verify there is an ID and this user has not opted out if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { return null; } return { id: digiTrustId.id, - keyv: digiTrustId.keyv, - pref: 0 + keyv: digiTrustId.keyv }; } @@ -334,7 +338,7 @@ const LEGACY_PROTOCOL = { _appendSiteAppDevice(request); - let digiTrust = _getDigiTrustQueryParams(); + let digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); if (digiTrust) { request.digiTrust = digiTrust; } @@ -521,26 +525,39 @@ const OPEN_RTB_PROTOCOL = { _appendSiteAppDevice(request); - const digiTrust = _getDigiTrustQueryParams(); + const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); if (digiTrust) { - request.user = { ext: { digitrust: digiTrust } }; + utils.deepSetValue(request, 'user.ext.digitrust', digiTrust); } if (!utils.isEmpty(aliases)) { request.ext.prebid.aliases = aliases; } - if (bidRequests && bidRequests[0].userId && typeof bidRequests[0].userId === 'object') { - if (!request.user) { - request.user = {}; - } - if (!request.user.ext) { - request.user.ext = {} + const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId'); + if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid)) { + utils.deepSetValue(request, 'user.ext.eids', []); + + if (bidUserId.tdid) { + request.user.ext.eids.push({ + source: 'adserver.org', + uids: [{ + id: bidUserId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }); } - if (!request.user.ext.tpid) { - request.user.ext.tpid = {} + + if (bidUserId.pubcid) { + request.user.ext.eids.push({ + source: 'pubcommon', + uids: [{ + id: bidUserId.pubcid, + }] + }); } - Object.assign(request.user.ext.tpid, bidRequests[0].userId); } if (bidRequests && bidRequests[0].gdprConsent) { @@ -560,16 +577,7 @@ const OPEN_RTB_PROTOCOL = { request.regs = { ext: { gdpr: gdprApplies } }; } - let consentString = bidRequests[0].gdprConsent.consentString; - if (request.user) { - if (request.user.ext) { - request.user.ext.consent = consentString; - } else { - request.user.ext = { consent: consentString }; - } - } else { - request.user = { ext: { consent: consentString } }; - } + utils.deepSetValue(request, 'user.ext.consent', bidRequests[0].gdprConsent.consentString); } return request; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index a0e9c89a221..abeebd2e1b2 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -14,6 +14,18 @@ export const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.j export const VIDEO_ENDPOINT = '//prebid-server.rubiconproject.com/openrtb2/auction'; export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; +const DIGITRUST_PROP_NAMES = { + FASTLANE: { + id: 'dt.id', + keyv: 'dt.keyv', + pref: 'dt.pref' + }, + PREBID_SERVER: { + id: 'id', + keyv: 'keyv' + } +}; + var sizeMap = { 1: '468x60', 2: '728x90', @@ -170,13 +182,9 @@ export const spec = { addVideoParameters(data, bidRequest); - const digiTrust = getDigiTrustQueryParams(); + const digiTrust = _getDigiTrustQueryParams(bidRequest, 'PREBID_SERVER'); if (digiTrust) { - data.user = { - ext: { - digitrust: digiTrust - } - }; + utils.deepSetValue(data, 'user.ext.digitrust', digiTrust); } if (bidderRequest.gdprConsent) { @@ -196,15 +204,32 @@ export const spec = { data.regs = {ext: {gdpr: gdprApplies}}; } - const consentString = bidderRequest.gdprConsent.consentString; - if (data.user) { - if (data.user.ext) { - data.user.ext.consent = consentString; - } else { - data.user.ext = {consent: consentString}; - } - } else { - data.user = {ext: {consent: consentString}}; + utils.deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + } + + if (bidRequest.userId && typeof bidRequest.userId === 'object' && + (bidRequest.userId.tdid || bidRequest.userId.pubcid)) { + utils.deepSetValue(data, 'user.ext.eids', []); + + if (bidRequest.userId.tdid) { + data.user.ext.eids.push({ + source: 'adserver.org', + uids: [{ + id: bidRequest.userId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }); + } + + if (bidRequest.userId.pubcid) { + data.user.ext.eids.push({ + source: 'pubcommon', + uids: [{ + id: bidRequest.userId.pubcid, + }] + }); } } @@ -406,10 +431,8 @@ export const spec = { } // digitrust properties - const digitrustParams = _getDigiTrustQueryParams(); - Object.keys(digitrustParams).forEach(paramKey => { - data[paramKey] = digitrustParams[paramKey]; - }); + const digitrustParams = _getDigiTrustQueryParams(bidRequest, 'FASTLANE'); + Object.assign(data, digitrustParams); return data; }, @@ -600,22 +623,36 @@ function _getScreenResolution() { return [window.screen.width, window.screen.height].join('x'); } -function _getDigiTrustQueryParams() { +function _getDigiTrustQueryParams(bidRequest = {}, endpointName) { + if (!endpointName || !DIGITRUST_PROP_NAMES[endpointName]) { + return null; + } + const propNames = DIGITRUST_PROP_NAMES[endpointName]; + function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); + const bidRequestDigitrust = utils.deepAccess(bidRequest, 'userId.digitrustid.data'); + if (bidRequestDigitrust) { + return bidRequestDigitrust; + } + + let digiTrustUser = (window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'}))); return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; } let digiTrustId = getDigiTrustId(); // Verify there is an ID and this user has not opted out if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return []; + return null; } - return { - 'dt.id': digiTrustId.id, - 'dt.keyv': digiTrustId.keyv, - 'dt.pref': 0 + + const digiTrustQueryParams = { + [propNames.id]: digiTrustId.id, + [propNames.keyv]: digiTrustId.keyv }; + if (propNames.pref) { + digiTrustQueryParams[propNames.pref] = 0; + } + return digiTrustQueryParams; } /** @@ -677,24 +714,6 @@ function parseSizes(bid, mediaType) { return masSizeOrdering(sizes); } -function getDigiTrustQueryParams() { - function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})); - return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; - } - - let digiTrustId = getDigiTrustId(); - // Verify there is an ID and this user has not opted out - if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return null; - } - return { - id: digiTrustId.id, - keyv: digiTrustId.keyv, - pref: 0 - }; -} - /** * @param {Object} data * @param bidRequest diff --git a/src/utils.js b/src/utils.js index ea80e970786..b5a46d174f4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -986,6 +986,23 @@ export function deepAccess(obj, path) { return obj; } +/** + * @param {Object} obj The object to set a deep property value in + * @param {(string|Array.)} path Object path to the value you would like ot set. + * @param {*} value The value you would like to set + */ +export function deepSetValue(obj, path, value) { + let i; + path = path.split('.'); + for (i = 0; i < path.length - 1; i++) { + if (i !== path.length - 1 && typeof obj[path[i]] === 'undefined') { + obj[path[i]] = {}; + } + obj = obj[path[i]]; + } + obj[path[i]] = value; +} + /** * Returns content for a friendly iframe to execute a URL in script tag * @param {string} url URL to be executed in a script tag in a friendly iframe diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 47d0084d86a..e2a3a5b111a 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -513,38 +513,37 @@ describe('S2S Adapter', function () { }); it('adds digitrust id is present and user is not optout', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + + let consentConfig = { s2sConfig: ortb2Config }; + config.setConfig(consentConfig); + let digiTrustObj = { - success: true, - identity: { - privacy: { - optout: false - }, - id: 'testId', - keyv: 'testKeyV' - } + privacy: { + optout: false + }, + id: 'testId', + keyv: 'testKeyV' }; - window.DigiTrust = { - getUser: () => digiTrustObj - }; + let digiTrustBidRequest = utils.deepClone(BID_REQUESTS); + digiTrustBidRequest[0].bids[0].userId = { digitrustid: { data: digiTrustObj } }; - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.digiTrust).to.deep.equal({ - id: digiTrustObj.identity.id, - keyv: digiTrustObj.identity.keyv, - pref: 0 + expect(requestBid.user.ext.digitrust).to.deep.equal({ + id: digiTrustObj.id, + keyv: digiTrustObj.keyv }); - digiTrustObj.identity.privacy.optout = true; + digiTrustObj.privacy.optout = true; - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax); requestBid = JSON.parse(requests[1].requestBody); - expect(requestBid.digiTrust).to.not.exist; - - delete window.DigiTrust; + expect(requestBid.user && request.user.ext && requestBid.user.ext.digitrust).to.not.exist; }); it('adds device and app objects to request', function () { @@ -813,22 +812,25 @@ describe('S2S Adapter', function () { it('when userId is defined on bids, it\'s properties should be copied to user.ext.tpid properties', function () { let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; let consentConfig = { s2sConfig: ortb2Config }; config.setConfig(consentConfig); let userIdBidRequest = utils.deepClone(BID_REQUESTS); - userIdBidRequest[0].userId = { - foo: 'abc123', - unifiedid: '1234' + userIdBidRequest[0].bids[0].userId = { + tdid: 'abc123', + pubcid: '1234' }; adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(requests[0].requestBody); - expect(typeof requestBid.user.ext.tpid).is.equal('object'); - expect(requestBid.user.ext.tpid.foo).is.equal('abc123'); - expect(requestBid.user.ext.tpid.unifiedid).is.equal('1234'); + expect(typeof requestBid.user.ext.eids).is.equal('object'); + expect(Array.isArray(requestBid.user.ext.eids)).to.be.true; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')).is.not.empty; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); }) it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { From 27e19dad6911cac72b91ed6a4c06e6b29ad43ab5 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Durgeat Date: Mon, 24 Jun 2019 19:05:50 +0200 Subject: [PATCH 031/436] ID5 userId submodule (#3798) * Extract GDPRApplies in userId.js to make it available to cookie-sync requiring it * Adding id5 userId submodule, tests and documentation * Fixed typo in test name for unifiedid * Adding test to userId for ID5 * Follow correct naming convention for GDPRApplies: renamed to isGDPRApplicable * Refactoring of id5 module following refactoring of userId module. * Moved init of id5 user module at the end of the id5 module itself * regroup import to avoid a CircleCI Bug --- integrationExamples/gpt/userId_example.html | 12 ++- modules/id5IdSystem.js | 60 +++++++++++++ modules/userId.js | 13 ++- modules/userId.md | 24 +++++- test/spec/modules/userId_spec.js | 95 +++++++++++++++------ 5 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 modules/id5IdSystem.js diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index d64e22e44c7..febe61628fe 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -140,7 +140,17 @@ name: "unifiedid", expires: 30 }, - + }, { + name: "id5Id", + params: { + partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io + }, + storage: { + type: "cookie", + name: "id5id", + expires: 90 + }, + }, { name: "pubCommonId", storage: { diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js new file mode 100644 index 00000000000..39ab256a81e --- /dev/null +++ b/modules/id5IdSystem.js @@ -0,0 +1,60 @@ +/** + * This module adds ID5 to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/unifiedIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils.js' +import {ajax} from '../src/ajax.js'; +import {isGDPRApplicable, attachIdSystem} from './userId.js'; + +/** @type {Submodule} */ +export const id5IdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'id5Id', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {{ID5ID:Object}} value + * @returns {{id5id:String}} + */ + decode(value) { + return (value && typeof value['ID5ID'] === 'string') ? { 'id5id': value['ID5ID'] } : undefined; + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @param {ConsentData} [consentData] + * @returns {function(callback:function)} + */ + getId(configParams, consentData) { + if (!configParams || typeof configParams.partner !== 'number') { + utils.logError(`User ID - ID5 submodule requires partner to be defined as a number`); + return; + } + const hasGdpr = isGDPRApplicable(consentData) ? 1 : 0; + const gdprConsentString = hasGdpr ? consentData.consentString : ''; + const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`; + + return function (callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj); + }, undefined, { method: 'GET' }); + } + } +}; + +attachIdSystem(id5IdSubmodule); diff --git a/modules/userId.js b/modules/userId.js index ae06dfc4027..c80ea21a0a0 100644 --- a/modules/userId.js +++ b/modules/userId.js @@ -158,13 +158,22 @@ function getStoredValue(storage) { return storedValue; } +/** + * test if consent module is present, and if GDPR applies + * @param {ConsentData} consentData + * @returns {boolean} + */ +export function isGDPRApplicable(consentData) { + return consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies; +} + /** * test if consent module is present, applies, and is valid for local storage or cookies (purpose 1) * @param {ConsentData} consentData * @returns {boolean} */ -function hasGDPRConsent(consentData) { - if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) { +export function hasGDPRConsent(consentData) { + if (isGDPRApplicable(consentData)) { if (!consentData.consentString) { return false; } diff --git a/modules/userId.md b/modules/userId.md index 782e7782554..b36b9b1007c 100644 --- a/modules/userId.md +++ b/modules/userId.md @@ -3,12 +3,12 @@ Example showing `cookie` storage for user id data for both submodules ``` pbjs.setConfig({ - userSync: { + usersync: { userIds: [{ name: "unifiedId", params: { partner: "prebid", - url: "//match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" + url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json" }, storage: { type: "cookie", @@ -28,6 +28,26 @@ pbjs.setConfig({ }); ``` +Example showing `cookie` storage for user id data for id5 submodule +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: "id5Id", + params: { + partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io + }, + storage: { + type: "cookie", + name: "id5id", + expires: 90 + } + }], + syncDelay: 5000 + } +}); +``` + Example showing `localStorage` for user id data for both submodules ``` pbjs.setConfig({ diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index d0f5e06cdad..60df468a903 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -9,18 +9,20 @@ import {config} from 'src/config'; import * as utils from 'src/utils'; import {unifiedIdSubmodule} from 'modules/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/pubCommonIdSystem'; +import {id5IdSubmodule} from 'modules/id5IdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { - function getConfigMock(configArr1, configArr2) { + function getConfigMock(configArr1, configArr2, configArr3) { return { userSync: { syncDelay: 0, userIds: [ (configArr1 && configArr1.length === 3) ? getStorageMock.apply(null, configArr1) : null, - (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null + (configArr2 && configArr2.length === 3) ? getStorageMock.apply(null, configArr2) : null, + (configArr3 && configArr3.length === 3) ? getStorageMock.apply(null, configArr3) : null ].filter(i => i)} } } @@ -68,7 +70,7 @@ describe('User ID', function() { let pubcid = utils.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); @@ -94,7 +96,7 @@ describe('User ID', function() { let pubcid1; let pubcid2; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); @@ -108,7 +110,7 @@ describe('User ID', function() { }); }); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); @@ -129,7 +131,7 @@ describe('User ID', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); @@ -164,14 +166,14 @@ describe('User ID', function() { }); it('fails initialization if opt out cookie exists', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - opt-out cookie found, exit module'); }); it('initializes if no opt out cookie exists', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); @@ -190,7 +192,7 @@ describe('User ID', function() { }); it('handles config with no usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({}); // usersync is undefined, and no logInfo message for 'User ID - usersync config updated' @@ -198,14 +200,14 @@ describe('User ID', function() { }); it('handles config with empty usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: {} }); expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); it('handles config with usersync and userIds that are empty objs', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -216,7 +218,7 @@ describe('User ID', function() { }); it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -233,15 +235,15 @@ describe('User ID', function() { }); it('config with 1 configurations should create 1 submodules', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); - it('config with 2 configurations should result in 2 submodules add', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + it('config with 3 configurations should result in 3 submodules add', function () { + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -251,14 +253,17 @@ describe('User ID', function() { }, { name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } + }, { + name: 'id5Id', + storage: { name: 'id5id', type: 'cookie' } }] } }); - expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 2 submodules'); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 3 submodules'); }); it('config syncDelay updates module correctly', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ usersync: { @@ -322,7 +327,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from pubcommonid html5', function(done) { + it('test hook from unifiedid html5', function(done) { // simulate existing browser local storage values localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); @@ -344,13 +349,36 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when both pubCommonId and unifiedId have data to pass', function(done) { + it('test hook from id5id cookies', function(done) { + // simulate existing browser local storage values + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + + setSubmoduleRegistry([id5IdSubmodule]); + init(config); + config.setConfig(getConfigMock(['id5Id', 'id5id', 'cookie'])); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); + }); + }); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + + it('test hook when pubCommonId, unifiedId and id5Id have data to pass', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'])); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -361,17 +389,22 @@ describe('User ID', function() { // also check that UnifiedId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.tdid'); expect(bid.userId.tdid).to.equal('testunifiedid'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); - it('test hook when pubCommonId and unifiedId have their modules added before and after init', function(done) { + it('test hook when pubCommonId, unifiedId and id5Id have their modules added before and after init', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -382,8 +415,11 @@ describe('User ID', function() { // attaching after init attachIdSystem(unifiedIdSubmodule); + attachIdSystem(id5IdSubmodule); - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'])); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -394,10 +430,14 @@ describe('User ID', function() { // also check that UnifiedId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.tdid'); expect(bid.userId.tdid).to.equal('cookie-value-add-module-variations'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); }); }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -405,9 +445,10 @@ describe('User ID', function() { it('should add new id system ', function(done) { utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule]); init(config); config.setConfig({ @@ -417,6 +458,8 @@ describe('User ID', function() { name: 'pubCommonId', storage: { name: 'pubcid', type: 'cookie' } }, { name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } + }, { + name: 'id5Id', storage: { name: 'id5id', type: 'cookie' } }, { name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } }] @@ -445,6 +488,9 @@ describe('User ID', function() { // check UnifiedId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.tdid'); expect(bid.userId.tdid).to.equal('cookie-value-add-module-variations'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.mid'); expect(bid.userId.mid).to.equal('123456778'); @@ -452,6 +498,7 @@ describe('User ID', function() { }); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); From c9a57f7c9fbb8dbaf854cfece6f533895495493d Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Mon, 24 Jun 2019 15:39:48 -0400 Subject: [PATCH 032/436] EMX Digital: Device info and Video parameter updates (#3929) * EMX Digital - device info and video parameter updates * update timeout value to grab from bidderRequest arg * removing unused import * removing object spread use. quote fix for lint * remove space --- modules/emx_digitalBidAdapter.js | 85 +++++++++++++------ .../modules/emx_digitalBidAdapter_spec.js | 7 +- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 69e02d5c860..2ca595151f9 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -1,13 +1,14 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { BANNER, VIDEO } from '../src/mediaTypes'; -import { config } from '../src/config'; import { Renderer } from '../src/Renderer'; import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; +const ADAPTER_VERSION = '1.40.2'; +const DEFAULT_CUR = 'USD'; export const emxAdapter = { validateSizes: (sizes) => { @@ -48,6 +49,23 @@ export const emxAdapter = { } return bidResponse; }, + isMobile: () => { + return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); + }, + isConnectedTV: () => { + return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); + }, + getDevice: () => { + return { + ua: navigator.userAgent, + js: 1, + dnt: (navigator.doNotTrack === 'yes' || navigator.doNotTrack === '1' || navigator.msDoNotTrack === '1') ? 1 : 0, + h: screen.height, + w: screen.width, + devicetype: emxAdapter.isMobile() ? 1 : emxAdapter.isConnectedTV() ? 3 : 2, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + }; + }, cleanProtocols: (video) => { if (video.protocols && includes(video.protocols, 7)) { // not supporting VAST protocol 7 (VAST 4.0); @@ -85,10 +103,22 @@ export const emxAdapter = { return renderer; }, buildVideo: (bid) => { - bid.params.video = bid.params.video || {}; - bid.params.video.h = bid.mediaTypes.video.playerSize[0][0]; - bid.params.video.w = bid.mediaTypes.video.playerSize[0][1]; - return emxAdapter.cleanProtocols(bid.params.video); + let videoObj = Object.assign(bid.mediaTypes.video, bid.params.video) + return emxAdapter.cleanProtocols(videoObj); + }, + parseResponse: (bidResponseAdm) => { + try { + return decodeURIComponent(bidResponseAdm); + } catch (err) { + utils.logError('emx_digitalBidAdapter', 'error', err); + } + }, + getReferrer: () => { + try { + return window.top.document.referrer; + } catch (err) { + return document.referrer; + } }, getGdpr: (bidRequests, emxData) => { if (bidRequests.gdprConsent) { @@ -151,40 +181,44 @@ export const spec = { return true; }, buildRequests: function (validBidRequests, bidderRequest) { - const page = bidderRequest.refererInfo.referer; - let emxImps = []; - const timeout = config.getConfig('bidderTimeout'); + const emxImps = []; + const timeout = bidderRequest.timeout || ''; const timestamp = Date.now(); - const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp); - const networkProtocol = location.protocol.indexOf('https') > -1 ? 1 : 0; + const url = location.protocol + '//' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp + '&src=pbjs'); + const secure = location.protocol.indexOf('https') > -1 ? 1 : 0; + const domain = utils.getTopWindowLocation().hostname; + const page = bidderRequest.refererInfo.referer; + const device = emxAdapter.getDevice(); + const ref = emxAdapter.getReferrer(); utils._each(validBidRequests, function (bid) { - let tagId = utils.getBidIdParameter('tagid', bid.params); - let bidFloor = parseFloat(utils.getBidIdParameter('bidfloor', bid.params)) || 0; + let tagid = utils.getBidIdParameter('tagid', bid.params); + let bidfloor = parseFloat(utils.getBidIdParameter('bidfloor', bid.params)) || 0; let isVideo = !!bid.mediaTypes.video; let data = { id: bid.bidId, tid: bid.transactionId, - tagid: tagId, - secure: networkProtocol + tagid, + secure }; let typeSpecifics = isVideo ? { video: emxAdapter.buildVideo(bid) } : { banner: emxAdapter.buildBanner(bid) }; - let emxBid = Object.assign(data, typeSpecifics); + let bidfloorObj = bidfloor > 0 ? { bidfloor, bidfloorcur: DEFAULT_CUR } : {}; + let emxBid = Object.assign(data, typeSpecifics, bidfloorObj); - if (bidFloor > 0) { - emxBid.bidfloor = bidFloor - } emxImps.push(emxBid); }); let emxData = { id: bidderRequest.auctionId, imp: emxImps, + device, site: { - domain: window.top.document.location.host, - page: page + domain, + page, + ref }, - version: '1.30.0' + cur: DEFAULT_CUR, + version: ADAPTER_VERSION }; emxData = emxAdapter.getGdpr(bidderRequest, Object.assign({}, emxData)); @@ -204,6 +238,7 @@ export const spec = { response.seatbid.forEach(function (emxBid) { emxBid = emxBid.bid[0]; let isVideo = false; + let adm = emxAdapter.parseResponse(emxBid.adm) || ''; let bidResponse = { requestId: emxBid.id, cpm: emxBid.price, @@ -214,7 +249,7 @@ export const spec = { currency: 'USD', netRevenue: true, ttl: emxBid.ttl, - ad: decodeURIComponent(emxBid.adm) + ad: adm }; if (emxBid.adm && emxBid.adm.indexOf(' -1) { isVideo = true; @@ -234,12 +269,6 @@ export const spec = { url: '//biddr.brealtime.com/check.html' }); } - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: '//edba.brealtime.com/' - }); - } return syncs; } }; diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index 170e5676f43..10d0d74c49c 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -276,8 +276,9 @@ describe('emx_digital Adapter', function () { it('properly sends site information and protocol', function () { request = spec.buildRequests(bidderRequest.bids, bidderRequest); request = JSON.parse(request.data); - expect(request.site.domain).to.equal(window.top.document.location.host); + expect(request.site.domain).to.equal(utils.getTopWindowLocation().hostname); expect(decodeURIComponent(request.site.page)).to.equal(bidderRequest.refererInfo.referer); + expect(request.site.ref).to.equal(window.top.document.referrer); }); it('builds correctly formatted request banner object', function () { @@ -511,10 +512,6 @@ describe('emx_digital Adapter', function () { let iframeSync = spec.getUserSyncs(syncOptionsIframe); expect(iframeSync.length).to.equal(1); expect(iframeSync[0].type).to.equal('iframe'); - - let pixelSync = spec.getUserSyncs(syncOptionsPixel); - expect(pixelSync.length).to.equal(1); - expect(pixelSync[0].type).to.equal('image'); }); }); }); From fc1e5bd2baee0f12c44bbede2d145305a101f21e Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 24 Jun 2019 13:40:40 -0600 Subject: [PATCH 033/436] update placementId to be number instead of string (#3941) --- integrationExamples/gpt/prebidServer_example.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationExamples/gpt/prebidServer_example.html b/integrationExamples/gpt/prebidServer_example.html index f13c93963c6..db61a6a46d6 100644 --- a/integrationExamples/gpt/prebidServer_example.html +++ b/integrationExamples/gpt/prebidServer_example.html @@ -41,7 +41,7 @@ { bidder: 'appnexus', params: { - placementId: '13144370' + placementId: 13144370 } } ] From 8b4c78de86acc30005644ec4534e004b235fbec8 Mon Sep 17 00:00:00 2001 From: Gleb Glushtsov Date: Mon, 24 Jun 2019 20:21:30 -0400 Subject: [PATCH 034/436] [33Across adapter] Map ad unit path to element id (#3920) * fix return of _mapAdUnitPathToElementId() * improve logging of _mapAdUnitPathToElementId() * do not use Array.find() * return id once element is found * return id once element is found * let -> const --- modules/33acrossBidAdapter.js | 48 ++++++++++++++------ modules/33acrossBidAdapter.md | 2 +- test/spec/modules/33acrossBidAdapter_spec.js | 4 +- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 1cf885ed6e4..801a5d564a3 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,8 +1,7 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; import * as utils from '../src/utils'; -const { registerBidder } = require('../src/adapters/bidderFactory'); -const { config } = require('../src/config'); - const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; @@ -32,17 +31,43 @@ function _isViewabilityMeasurable(element) { } function _getViewability(element, topWin, { w, h } = {}) { - return utils.getWindowTop().document.visibilityState === 'visible' + return topWin.document.visibilityState === 'visible' ? _getPercentInView(element, topWin, { w, h }) : 0; } +function _mapAdUnitPathToElementId(adUnitCode) { + if (utils.isGptPubadsDefined()) { + const adSlots = googletag.pubads().getSlots(); + const isMatchingAdSlot = utils.isSlotMatchingAdUnitCode(adUnitCode); + + for (let i = 0; i < adSlots.length; i++) { + if (isMatchingAdSlot(adSlots[i])) { + const id = adSlots[i].getSlotElementId(); + + utils.logInfo(`[33Across Adapter] Map ad unit path to HTML element id: '${adUnitCode}' -> ${id}`); + + return id; + } + } + } + + utils.logWarn(`[33Across Adapter] Unable to locate element for ad unit code: '${adUnitCode}'`); + + return null; +} + +function _getAdSlotHTMLElement(adUnitCode) { + return document.getElementById(adUnitCode) || + document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); +} + // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request // NOTE: At this point, TTX only accepts request for a single impression function _createServerRequest(bidRequest, gdprConsent) { const ttxRequest = {}; const params = bidRequest.params; - const element = document.getElementById(bidRequest.adUnitCode); + const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); const sizes = _transformSizes(bidRequest.sizes); const minSize = _getMinSize(sizes); @@ -52,10 +77,6 @@ function _createServerRequest(bidRequest, gdprConsent) { const contributeViewability = ViewabilityContributor(viewabilityAmount); - if (element === null) { - utils.logWarn(`Unable to locate element with id: '${bidRequest.adUnitCode}'`); - } - /* * Infer data for the request payload */ @@ -264,13 +285,14 @@ function isBidRequestValid(bid) { // - the server, at this point, also doesn't need the consent string to handle gdpr compliance. So passing // value whether set or not, for the sake of future dev. function buildRequests(bidRequests, bidderRequest) { - const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent); + const gdprConsent = Object.assign({ + consentString: undefined, + gdprApplies: false + }, bidderRequest && bidderRequest.gdprConsent); adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); - return bidRequests.map((req) => { - return _createServerRequest(req, gdprConsent); - }); + return bidRequests.map(req => _createServerRequest(req, gdprConsent)); } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid diff --git a/modules/33acrossBidAdapter.md b/modules/33acrossBidAdapter.md index bdb2b944861..58e3b2b273a 100644 --- a/modules/33acrossBidAdapter.md +++ b/modules/33acrossBidAdapter.md @@ -16,7 +16,7 @@ Connects to 33Across's exchange for bids. ``` var adUnits = [ { - code: '33across-hb-ad-123456-1', + code: '33across-hb-ad-123456-1', // ad slot HTML element ID sizes: [ [300, 250], [728, 90] diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 1fc77a7e14d..7e1a8619c63 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -337,8 +337,8 @@ describe('33acrossBidAdapter:', function () { utils.getWindowTop.restore(); utils.getWindowSelf.restore(); - sandbox.stub(utils, 'getWindowTop').returns(win); - sandbox.stub(utils, 'getWindowSelf').returns({}); + sandbox.stub(utils, 'getWindowTop').returns({}); + sandbox.stub(utils, 'getWindowSelf').returns(win); expect(spec.buildRequests(bidRequests)).to.deep.equal([ serverRequest ]); }); From 9c81338e8251c1d335769faae661fdca93bd89ef Mon Sep 17 00:00:00 2001 From: Daniel Liebner Date: Tue, 25 Jun 2019 13:36:02 -0400 Subject: [PATCH 035/436] New Adapter: bidglass (#3861) * Added bidglass adapter + test * PR Review Updates: - Added formal params to getUserSyncs function definition - getUserSyncs now always returns an array - Improved unit test coverage * PR Review Updates: - Removed unused methods: getUserSyncs, onTimeout, onBidWon, onSetTargeting - Removed getUserSyncs unit test - Removed "dead code" - Removed some unnecessary comments - Fixed usage of parseInt --- modules/bidglassBidAdapter.js | 134 ++++++++++++++++++++++ modules/bidglassBidAdapter.md | 34 ++++++ test/spec/modules/bidglassAdapter_spec.js | 103 +++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 modules/bidglassBidAdapter.js create mode 100644 modules/bidglassBidAdapter.md create mode 100644 test/spec/modules/bidglassAdapter_spec.js diff --git a/modules/bidglassBidAdapter.js b/modules/bidglassBidAdapter.js new file mode 100644 index 00000000000..1898d1220fa --- /dev/null +++ b/modules/bidglassBidAdapter.js @@ -0,0 +1,134 @@ +import * as utils from 'src/utils'; +// import {config} from 'src/config'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'bidglass'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['bg'], // short code + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + return !!(bid.params.adUnitId && !isNaN(parseFloat(bid.params.adUnitId)) && isFinite(bid.params.adUnitId)); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + /* + Sample array entry for validBidRequests[]: + [{ + "bidder": "bidglass", + "bidId": "51ef8751f9aead", + "params": { + "adUnitId": 11, + ... + }, + "adUnitCode": "div-gpt-ad-1460505748561-0", + "transactionId": "d7b773de-ceaa-484d-89ca-d9f51b8d61ec", + "sizes": [[320,50],[300,250],[300,600]], + "bidderRequestId": "418b37f85e772c", + "auctionId": "18fd8b8b0bd757", + "bidRequestsCount": 1 + }] + */ + + let imps = []; + let getReferer = function() { + return window === window.top ? window.location.href : window.parent === window.top ? document.referrer : null; + }; + let getOrigins = function() { + var ori = [window.location.protocol + '//' + window.location.hostname]; + + if (window.location.ancestorOrigins) { + for (var i = 0; i < window.location.ancestorOrigins.length; i++) { + ori.push(window.location.ancestorOrigins[i]); + } + } else if (window !== window.top) { + // Derive the parent origin + var parts = document.referrer.split('/'); + + ori.push(parts[0] + '//' + parts[2]); + + if (window.parent !== window.top) { + // Additional unknown origins exist + ori.push('null'); + } + } + + return ori; + }; + + utils._each(validBidRequests, function(bid) { + bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]); + bid.sizes = bid.sizes.filter(size => utils.isArray(size)); + + // Stuff to send: [bid id, sizes, adUnitId] + imps.push({ + bidId: bid.bidId, + sizes: bid.sizes, + adUnitId: utils.getBidIdParameter('adUnitId', bid.params) + }); + }); + + // Stuff to send: page URL + const bidReq = { + reqId: utils.getUniqueIdentifierStr(), + imps: imps, + ref: getReferer(), + ori: getOrigins() + }; + + let url = 'https://bid.glass/ad/hb.php?' + + `src=$$REPO_AND_VERSION$$`; + + return { + method: 'POST', + url: url, + data: JSON.stringify(bidReq), + options: { + contentType: 'text/plain', + withCredentials: false + } + } + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse) { + const bidResponses = []; + + utils._each(serverResponse.body.bidResponses, function(bid) { + bidResponses.push({ + requestId: bid.requestId, + cpm: parseFloat(bid.cpm), + width: parseInt(bid.width, 10), + height: parseInt(bid.height, 10), + creativeId: bid.creativeId, + dealId: bid.dealId || null, + currency: bid.currency || 'USD', + mediaType: bid.mediaType || 'banner', + netRevenue: true, + ttl: bid.ttl || 10, + ad: bid.ad + }); + }); + + return bidResponses; + } + +} + +registerBidder(spec); diff --git a/modules/bidglassBidAdapter.md b/modules/bidglassBidAdapter.md new file mode 100644 index 00000000000..5384a095314 --- /dev/null +++ b/modules/bidglassBidAdapter.md @@ -0,0 +1,34 @@ +# Overview + +``` +Module Name: Bid Glass Bid Adapter +Module Type: Bidder Adapter +Maintainer: dliebner@gmail.com +``` + +# Description + +Connects to Bid Glass and allows bids on ad units to compete within prebid. + +# Sample Ad Unit: For Publishers +``` +var adUnits = [{ + code: 'bg-test-rectangle', + sizes: [[300, 250]], + bids: [{ + bidder: 'bidglass', + params: { + adUnitId: '-1' + } + }] +},{ + code: 'bg-test-leaderboard', + sizes: [[728, 90]], + bids: [{ + bidder: 'bidglass', + params: { + adUnitId: '-1' + } + }] +}] +``` \ No newline at end of file diff --git a/test/spec/modules/bidglassAdapter_spec.js b/test/spec/modules/bidglassAdapter_spec.js new file mode 100644 index 00000000000..00a47fc997a --- /dev/null +++ b/test/spec/modules/bidglassAdapter_spec.js @@ -0,0 +1,103 @@ +import { expect } from 'chai'; +import { spec } from 'modules/bidglassBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Bid Glass Adapter', function () { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'bidglass', + 'params': { + 'adUnitId': '3' + }, + 'adUnitCode': 'bidglass-testunit', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [{ + 'bidder': 'bidglass', + 'params': { + 'adUnitId': '3' + }, + 'adUnitCode': 'bidglass-testunit', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', function () { + expect(request.method).to.equal('POST'); + }); + + it('sets withCredentials to false', function () { + expect(request.options.withCredentials).to.equal(false); + }); + }); + + describe('interpretResponse', function () { + let response; + beforeEach(function () { + response = { + body: { + 'bidResponses': [{ + 'ad': '', + 'cpm': '0.01', + 'creativeId': '-1', + 'width': '300', + 'height': '250', + 'requestId': '30b31c1838de1e' + }] + } + }; + }); + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '30b31c1838de1e', + 'cpm': 0.01, + 'width': 300, + 'height': 250, + 'creativeId': '-1', + 'dealId': null, + 'currency': 'USD', + 'mediaType': 'banner', + 'netRevenue': true, + 'ttl': 10, + 'ad': '' + }]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles empty bid response', function () { + let response = { + body: { + 'bidResponses': [] + } + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); From 406d30d4fe7319b971a4b9200cdf7bf2ac2e4e17 Mon Sep 17 00:00:00 2001 From: Index Exchange 3 Prebid Team Date: Tue, 25 Jun 2019 13:37:06 -0400 Subject: [PATCH 036/436] Prebid.js Video (#3901) * Implemented changes required to provide support for video in the IX bidding adapter for Instream and Outstream contexts. * Implemented changes required to provide support for video in the IX bidding adapter for Instream and Outstream contexts. * fix find module --- modules/ixBidAdapter.js | 366 ++++++++++++++++--------- modules/ixBidAdapter.md | 128 ++++++++- test/spec/modules/ixBidAdapter_spec.js | 344 ++++++++++++++++++----- 3 files changed, 628 insertions(+), 210 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index c63b920dc93..f26c5e413c5 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,38 +1,75 @@ import * as utils from '../src/utils'; -import { BANNER } from '../src/mediaTypes'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; import { config } from '../src/config'; import isArray from 'core-js/library/fn/array/is-array'; import isInteger from 'core-js/library/fn/number/is-integer'; import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'ix'; -const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; -const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; -const SUPPORTED_AD_TYPES = [BANNER]; -const ENDPOINT_VERSION = 7.2; +const SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; +const INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const BANNER_ENDPOINT_VERSION = 7.2; +const VIDEO_ENDPOINT_VERSION = 8.1; + const CENT_TO_DOLLAR_FACTOR = 100; -const TIME_TO_LIVE = 35; +const BANNER_TIME_TO_LIVE = 35; +const VIDEO_TIME_TO_LIVE = 3600; // 1hr const NET_REVENUE = true; const PRICE_TO_DOLLAR_FACTOR = { JPY: 1 }; /** - * Transform valid bid request config object to impression object that will be sent to ad server. + * Transform valid bid request config object to banner impression object that will be sent to ad server. * * @param {object} bid A valid bid request config object. * @return {object} A impression object that will be sent to ad server. */ function bidToBannerImp(bid) { - const imp = {}; - - imp.id = bid.bidId; + const imp = bidToImp(bid); imp.banner = {}; imp.banner.w = bid.params.size[0]; imp.banner.h = bid.params.size[1]; imp.banner.topframe = utils.inIframe() ? 0 : 1; + return imp; +} + +/** + * Transform valid bid request config object to video impression object that will be sent to ad server. + * + * @param {object} bid A valid bid request config object. + * @return {object} A impression object that will be sent to ad server. + */ +function bidToVideoImp(bid) { + const imp = bidToImp(bid); + + imp.video = utils.deepClone(bid.params.video) + imp.video.w = bid.params.size[0]; + imp.video.h = bid.params.size[1]; + + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (context) { + if (context === 'instream') { + imp.video.placement = 1; + } else if (context === 'outstream') { + imp.video.placement = 4; + } else { + utils.logWarn(`ix bidder params: video context '${context}' is not supported`); + } + } + + return imp; +} + +function bidToImp(bid) { + const imp = {}; + + imp.id = bid.bidId; + imp.ext = {}; imp.ext.siteID = bid.params.siteId; @@ -58,7 +95,7 @@ function bidToBannerImp(bid) { * @param {string} currency Global currency in bid response. * @return {object} bid The parsed bid. */ -function parseBid(rawBid, currency) { +function parseBid(rawBid, currency, bidRequest) { const bid = {}; if (PRICE_TO_DOLLAR_FACTOR.hasOwnProperty(currency)) { @@ -68,15 +105,27 @@ function parseBid(rawBid, currency) { } bid.requestId = rawBid.impid; - bid.width = rawBid.w; - bid.height = rawBid.h; - bid.ad = rawBid.adm; + bid.dealId = utils.deepAccess(rawBid, 'ext.dealid'); - bid.ttl = TIME_TO_LIVE; bid.netRevenue = NET_REVENUE; bid.currency = currency; bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; + // in the event of a video + if (utils.deepAccess(rawBid, 'ext.vasturl')) { + bid.vastUrl = rawBid.ext.vasturl + bid.width = bidRequest.video.w; + bid.height = bidRequest.video.h; + bid.mediaType = VIDEO; + bid.ttl = VIDEO_TIME_TO_LIVE; + } else { + bid.ad = rawBid.adm; + bid.width = rawBid.w; + bid.height = rawBid.h; + bid.mediaType = BANNER; + bid.ttl = BANNER_TIME_TO_LIVE; + } + bid.meta = {}; bid.meta.networkId = utils.deepAccess(rawBid, 'ext.dspid'); bid.meta.brandId = utils.deepAccess(rawBid, 'ext.advbrandid'); @@ -133,6 +182,143 @@ function isValidBidFloorParams(bidFloor, bidFloorCur) { bidFloorCur.match(curRegex)); } +/** + * Finds the impression with the associated id. + * + * @param {*} id Id of the impression. + * @param {array} impressions List of impressions sent in the request. + * @return {object} The impression with the associated id. + */ +function getBidRequest(id, impressions) { + if (!id) { + return; + } + return find(impressions, imp => imp.id === id); +} + +/** + * Builds a request object to be sent to the ad server based on bid requests. + * + * @param {array} validBidRequests A list of valid bid request config objects. + * @param {object} bidderRequest An object containing other info like gdprConsent. + * @param {array} impressions List of impression objects describing the bids. + * @param {array} version Endpoint version denoting banner or video. + * @return {object} Info describing the request to the server. + * + */ +function buildRequest(validBidRequests, bidderRequest, impressions, version) { + const userEids = []; + + // Always start by assuming the protocol is HTTPS. This way, it will work + // whether the page protocol is HTTP or HTTPS. Then check if the page is + // actually HTTP.If we can guarantee it is, then, and only then, set protocol to + // HTTP. + let baseUrl = SECURE_BID_URL; + + // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded + // and if the data for the partner exist + if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { + let identityInfo = window.headertag.getIdentityInfo(); + if (identityInfo && typeof identityInfo === 'object') { + for (const partnerName in identityInfo) { + if (identityInfo.hasOwnProperty(partnerName)) { + let response = identityInfo[partnerName]; + if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { + userEids.push(response.data); + } + } + } + } + } + const r = {}; + + // Since bidderRequestId are the same for different bid request, just use the first one. + r.id = validBidRequests[0].bidderRequestId; + + r.imp = impressions; + + r.site = {}; + r.ext = {}; + r.ext.source = 'prebid'; + if (userEids.length > 0) { + r.user = {}; + r.user.eids = userEids; + } + + if (document.referrer && document.referrer !== '') { + r.site.ref = document.referrer; + } + + // Apply GDPR information to the request if GDPR is enabled. + if (bidderRequest) { + if (bidderRequest.gdprConsent) { + const gdprConsent = bidderRequest.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = r.user || {}; + r.user.ext = { + consent: gdprConsent.consentString || '' + }; + } + } + + if (bidderRequest.refererInfo) { + r.site.page = bidderRequest.refererInfo.referer; + + if (bidderRequest.refererInfo.referer && bidderRequest.refererInfo.referer.indexOf('https') !== 0) { + baseUrl = INSECURE_BID_URL; + } + } + } + + const payload = {}; + + // Parse additional runtime configs. + const otherIxConfig = config.getConfig('ix'); + if (otherIxConfig) { + // Append firstPartyData to r.site.page if firstPartyData exists. + if (typeof otherIxConfig.firstPartyData === 'object') { + const firstPartyData = otherIxConfig.firstPartyData; + let firstPartyString = '?'; + for (const key in firstPartyData) { + if (firstPartyData.hasOwnProperty(key)) { + firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; + } + } + firstPartyString = firstPartyString.slice(0, -1); + + r.site.page += firstPartyString; + } + + // Create t in payload if timeout is configured. + if (typeof otherIxConfig.timeout === 'number') { + payload.t = otherIxConfig.timeout; + } + } + + // Use the siteId in the first bid request as the main siteId. + payload.s = validBidRequests[0].params.siteId; + payload.v = version; + payload.r = JSON.stringify(r); + payload.ac = 'j'; + payload.sd = 1; + payload.nf = 1; + + return { + method: 'GET', + url: baseUrl, + data: payload + }; +} + export const spec = { code: BIDDER_CODE, @@ -146,22 +332,25 @@ export const spec = { */ isBidRequestValid: function (bid) { if (!isValidSize(bid.params.size)) { + utils.logError('ix bidder params: bid size has invalid format.'); return false; } if (!includesSize(bid.sizes, bid.params.size)) { + utils.logError('ix bidder params: bid size is not included in ad unit sizes.'); return false; } - if (bid.hasOwnProperty('mediaType') && bid.mediaType !== 'banner') { + if (bid.hasOwnProperty('mediaType') && !(utils.contains(SUPPORTED_AD_TYPES, bid.mediaType))) { return false; } - if (bid.hasOwnProperty('mediaTypes') && !utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { + if (bid.hasOwnProperty('mediaTypes') && !(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || utils.deepAccess(bid, 'mediaTypes.video.playerSize'))) { return false; } if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') { + utils.logError('ix bidder params: siteId must be string or number value.'); return false; } @@ -169,8 +358,10 @@ export const spec = { const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur'); if (hasBidFloor || hasBidFloorCur) { - return hasBidFloor && hasBidFloorCur && - isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur); + if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) { + utils.logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.'); + return false; + } } return true; @@ -180,139 +371,49 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} options A object contains bids and other info like gdprConsent. + * @param {object} bidderRequest A object contains bids and other info like gdprConsent. * @return {object} Info describing the request to the server. */ - buildRequests: function (validBidRequests, options) { - const bannerImps = []; - const userEids = []; + buildRequests: function (validBidRequests, bidderRequest) { + let reqs = []; + let bannerImps = []; + let videoImps = []; let validBidRequest = null; - let bannerImp = null; - - // Always start by assuming the protocol is HTTPS. This way, it will work - // whether the page protocol is HTTP or HTTPS. Then check if the page is - // actually HTTP.If we can guarantee it is, then, and only then, set protocol to - // HTTP. - let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { validBidRequest = validBidRequests[i]; - // Transform the bid request based on the banner format. - bannerImp = bidToBannerImp(validBidRequest); - bannerImps.push(bannerImp); - } - - // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded - // and if the data for the partner exist - if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { - let identityInfo = window.headertag.getIdentityInfo(); - if (identityInfo && typeof identityInfo === 'object') { - for (const partnerName in identityInfo) { - if (identityInfo.hasOwnProperty(partnerName)) { - let response = identityInfo[partnerName]; - if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { - userEids.push(response.data); - } - } - } - } - } - const r = {}; - - // Since bidderRequestId are the same for different bid request, just use the first one. - r.id = validBidRequests[0].bidderRequestId; - - r.imp = bannerImps; - r.site = {}; - r.ext = {}; - r.ext.source = 'prebid'; - if (userEids.length > 0) { - r.user = {}; - r.user.eids = userEids; - } - - if (document.referrer && document.referrer !== '') { - r.site.ref = document.referrer; - } - - // Apply GDPR information to the request if GDPR is enabled. - if (options) { - if (options.gdprConsent) { - const gdprConsent = options.gdprConsent; - - if (gdprConsent.hasOwnProperty('gdprApplies')) { - r.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - }; - } - - if (gdprConsent.hasOwnProperty('consentString')) { - r.user = r.user || {}; - r.user.ext = { - consent: gdprConsent.consentString || '' - }; + if (validBidRequest.mediaType === VIDEO || utils.deepAccess(validBidRequest, 'mediaTypes.video')) { + if (validBidRequest.mediaType === VIDEO || includesSize(validBidRequest.mediaTypes.video.playerSize, validBidRequest.params.size)) { + videoImps.push(bidToVideoImp(validBidRequest)); + } else { + utils.logError('Bid size is not included in video playerSize') } } - - if (options.refererInfo) { - r.site.page = options.refererInfo.referer; - - if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { - baseUrl = BANNER_INSECURE_BID_URL; - } + if (validBidRequest.mediaType === BANNER || utils.deepAccess(validBidRequest, 'mediaTypes.banner') || + (!validBidRequest.mediaType && !validBidRequest.mediaTypes)) { + bannerImps.push(bidToBannerImp(validBidRequest)); } } - const payload = {}; - - // Parse additional runtime configs. - const otherIxConfig = config.getConfig('ix'); - if (otherIxConfig) { - // Append firstPartyData to r.site.page if firstPartyData exists. - if (typeof otherIxConfig.firstPartyData === 'object') { - const firstPartyData = otherIxConfig.firstPartyData; - let firstPartyString = '?'; - for (const key in firstPartyData) { - if (firstPartyData.hasOwnProperty(key)) { - firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; - } - } - firstPartyString = firstPartyString.slice(0, -1); - - r.site.page += firstPartyString; - } - - // Create t in payload if timeout is configured. - if (typeof otherIxConfig.timeout === 'number') { - payload.t = otherIxConfig.timeout; - } + if (bannerImps.length > 0) { + reqs.push(buildRequest(validBidRequests, bidderRequest, bannerImps, BANNER_ENDPOINT_VERSION)); + } + if (videoImps.length > 0) { + reqs.push(buildRequest(validBidRequests, bidderRequest, videoImps, VIDEO_ENDPOINT_VERSION)); } - // Use the siteId in the first bid request as the main siteId. - payload.s = validBidRequests[0].params.siteId; - - payload.v = ENDPOINT_VERSION; - payload.r = JSON.stringify(r); - payload.ac = 'j'; - payload.sd = 1; - - return { - method: 'GET', - url: baseUrl, - data: payload - }; + return reqs; }, /** * Unpack the response from the server into a list of bids. * * @param {object} serverResponse A successful response from the server. + * @param {object} bidderRequest The bid request sent to the server. * @return {array} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse) { + interpretResponse: function (serverResponse, bidderRequest) { const bids = []; let bid = null; @@ -329,8 +430,11 @@ export const spec = { // Transform rawBid in bid response to the format that will be accepted by prebid. const innerBids = seatbid[i].bid; + let requestBid = JSON.parse(bidderRequest.data.r); + for (let j = 0; j < innerBids.length; j++) { - bid = parseBid(innerBids[j], responseBody.cur); + const bidRequest = getBidRequest(innerBids[j].impid, requestBid.imp); + bid = parseBid(innerBids[j], responseBody.cur, bidRequest); bids.push(bid); } } diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md index e99c42408f2..7bd60ac413b 100644 --- a/modules/ixBidAdapter.md +++ b/modules/ixBidAdapter.md @@ -42,16 +42,21 @@ var adUnits = [{ ```javascript var adUnits = [{ // ... - mediaTypes: { banner: { sizes: [ [300, 250], [300, 600] ] + }, + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] } - } - + }, // ... }]; ``` @@ -61,7 +66,7 @@ var adUnits = [{ | Type | Support | --- | --- | Banner | Fully supported for all IX approved sizes. -| Video | Not supported. +| Video | Fully supported for all IX approved sizes. | Native | Not supported. # Bid Parameters @@ -76,6 +81,17 @@ object are detailed here. | siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` | size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`. Examples: `[300, 250]`, `[300, 600]`, `[728, 90]` +### Video + +| Key | Scope | Type | Description +| --- | --- | --- | --- +| siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` +| size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.video.playerSize`. Examples: `[300, 250]`, `[300, 600]` +| video | Required | Hash | The video object will serve as the properties of the video ad. You can create any field under the video object that is mentioned in the `OpenRTB Spec v2.5`. Some fields like `mimes, protocols, minduration, maxduration` are required. +| video.mimes | Required | String[] | Array list of content MIME types supported. Popular MIME types include, but are not limited to, `"video/x-ms- wmv"` for Windows Media and `"video/x-flv"` for Flash Video. +|video.minduration| Required | Integer | Minimum video ad duration in seconds. +|video.maxduration| Required | Integer | Maximum video ad duration in seconds. +|video.protocol / video.protocols| Required | Integer / Integer[] | Either a single protocol provided as an integer, or protocols provided as a list of integers. `2` - VAST 2.0, `3` - VAST 3.0, `5` - VAST 2.0 Wrapper, `6` - VAST 3.0 Wrapper Setup Guide @@ -84,7 +100,9 @@ Setup Guide Follow these steps to configure and add the IX module to your Prebid.js integration. -The examples in this guide assume the following starting configuration: +The examples in this guide assume the following starting configuration (you may remove banner or video, if either does not apply). + +In regards to video, `context` can either be `'instream'` or `'outstream'`. Note that `outstream` requires additional configuration on the adUnit. ```javascript var adUnits = [{ @@ -98,6 +116,19 @@ var adUnits = [{ } }, bids: [] +}, +{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [] }]; ``` @@ -119,7 +150,9 @@ bid objects under `adUnits[].bids`: Set `params.siteId` and `params.size` in each bid object to the values provided by your IX representative. -**Example** +**Examples** + +**Banner:** ```javascript var adUnits = [{ code: 'banner-div-a', @@ -146,18 +179,94 @@ var adUnits = [{ }] }]; ``` - +**Video (Instream):** +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 250], + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0, + maxduration: 60, + protocols: [6] + } + } + }, { + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 600], + video: { + // openrtb v2.5 compatible video obj + } + } + }] +}]; +``` Please note that you can re-use the existing `siteId` within the same flex position. +**Video (Outstream):** +Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See http://prebid.org/dev-docs/show-outstream-video-ads.html for more information. +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[300, 250]] + } + }, + renderer: { + url: 'https://test.com/my-video-player.js', + render: function (bid) { + ... + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 250], + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0, + maxduration: 60, + protocols: [6] + } + } + }] +}]; +``` ##### 2. Include `ixBidAdapter` in your build process -When running the build command, include `ixBidAdapter` as a module. +When running the build command, include `ixBidAdapter` as a module, as well as `dfpAdServerVideo` if you require video support. ``` -gulp build --modules=ixBidAdapter,fooBidAdapter,bazBidAdapter +gulp build --modules=ixBidAdapter,dfpAdServerVideo,fooBidAdapter,bazBidAdapter ``` If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` @@ -166,6 +275,7 @@ to the top-level array in that file. ```json [ "ixBidAdapter", + "dfpAdServerVideo", "fooBidAdapter", "bazBidAdapter" ] diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 38e64e8d338..634d5041e6e 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -7,7 +7,8 @@ import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; - const BIDDER_VERSION = 7.2; + const VIDEO_ENDPOINT_VERSION = 8.1; + const BANNER_ENDPOINT_VERSION = 7.2; const DEFAULT_BANNER_VALID_BID = [ { @@ -29,17 +30,37 @@ describe('IndexexchangeAdapter', function () { auctionId: '1aa2bb3cc4dd' } ]; - const DEFAULT_BANNER_OPTION = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - referer: 'http://www.prebid.org', - canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + + const DEFAULT_VIDEO_VALID_BID = [ + { + bidder: 'ix', + params: { + siteId: '456', + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0 + }, + size: [400, 100] + }, + sizes: [[400, 100], [200, 400]], + mediaTypes: { + video: { + context: 'instream', + playerSize: [[400, 100], [200, 400]] + } + }, + adUnitCode: 'div-gpt-ad-1460505748562-0', + transactionId: '173f49a8-7549-4218-a23c-e7ba59b47230', + bidId: '1a2b3c4e', + bidderRequestId: '11a22b33c44e', + auctionId: '1aa2bb3cc4de' } - }; + ]; + const DEFAULT_BANNER_BID_RESPONSE = { cur: 'USD', id: '11a22b33c44d', @@ -69,6 +90,48 @@ describe('IndexexchangeAdapter', function () { } ] }; + + const DEFAULT_VIDEO_BID_RESPONSE = { + cur: 'USD', + id: '1aa2bb3cc4de', + seatbid: [ + { + bid: [ + { + crid: '12346', + adomain: ['www.abcd.com'], + adid: '14851456', + impid: '1a2b3c4e', + cid: '3051267', + price: 110, + id: '2', + ext: { + vasturl: 'www.abcd.com/vast', + errorurl: 'www.abcd.com/error', + dspid: 51, + pricelevel: '_110', + advbrandid: 303326, + advbrand: 'OECTB' + } + } + ], + seat: '3971' + } + ] + }; + + const DEFAULT_OPTION = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + }, + refererInfo: { + referer: 'http://www.prebid.org', + canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + } + }; + const DEFAULT_IDENTITY_RESPONSE = { IdentityIp: { responsePending: false, @@ -83,6 +146,31 @@ describe('IndexexchangeAdapter', function () { } }; + const DEFAULT_BIDDER_REQUEST_DATA = { + ac: 'j', + r: JSON.stringify({ + id: '345', + imp: [ + { + id: '1a2b3c4e', + video: { + w: 640, + h: 480, + placement: 1 + } + } + ], + site: { + ref: 'http://ref.com/ref.html', + page: 'http://page.com' + }, + }), + s: '21', + sd: 1, + t: 1000, + v: 8.1 + }; + describe('inherited functions', function () { it('should exists and is a function', function () { const adapter = newBidder(spec); @@ -91,11 +179,12 @@ describe('IndexexchangeAdapter', function () { }); describe('isBidRequestValid', function () { - it('should return true when required params found for a banner ad', function () { + it('should return true when required params found for a banner or video ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); + expect(spec.isBidRequestValid(DEFAULT_VIDEO_VALID_BID[0])).to.equal(true); }); - it('should return true when optional params found for a banner ad', function () { + it('should return true when optional bidFloor params found for an ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -136,10 +225,10 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes is not banner', function () { + it('should return false when mediaTypes is not banner or video', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { - video: { + native: { sizes: [[300, 250]] } }; @@ -156,19 +245,13 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaType is not banner', function () { - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - delete bid.params.mediaTypes; - bid.mediaType = 'banne'; - bid.sizes = [[300, 250]]; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when mediaType is video', function () { - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - delete bid.params.mediaTypes; - bid.mediaType = 'video'; - bid.sizes = [[300, 250]]; + it('should return false when mediaTypes.video does not have sizes', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + bid.mediaTypes = { + video: { + size: [[300, 250]] + } + }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -195,6 +278,14 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); + it('should return true when mediaType is video', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'video'; + bid.sizes = [[400, 100]]; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; @@ -232,7 +323,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return testCopy; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; }); afterEach(function() { @@ -343,7 +434,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return undefined; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -356,7 +447,7 @@ describe('IndexexchangeAdapter', function () { responsePending: true, data: {} } - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -366,7 +457,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending for all partners', function () { testCopy.IdentityIp.responsePending = true; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -377,7 +468,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending or not available for all partners', function () { testCopy.IdentityIp.responsePending = false; testCopy.IdentityIp.data = {}; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -387,8 +478,8 @@ describe('IndexexchangeAdapter', function () { }); }); - describe('buildRequestsBanner', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + describe('buildRequests', function () { + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const requestUrl = request.url; const requestMethod = request.method; const query = request.data; @@ -396,7 +487,7 @@ describe('IndexexchangeAdapter', function () { const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); delete bidWithoutMediaType[0].mediaTypes; bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; - const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_BANNER_OPTION); + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_OPTION)[0]; const queryWithoutMediaType = requestWithoutMediaType.data; it('request should be made to IX endpoint with GET method', function () { @@ -405,11 +496,12 @@ describe('IndexexchangeAdapter', function () { }); it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(BIDDER_VERSION); + expect(query.v).to.equal(BANNER_ENDPOINT_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; expect(query.ac).to.equal('j'); expect(query.sd).to.equal(1); + expect(query.nf).to.equal(1); }); it('payload should have correct format and value', function () { @@ -417,7 +509,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -445,7 +537,7 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.bidfloor).to.equal(bid.params.bidFloor); @@ -457,7 +549,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -484,7 +576,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 50; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); @@ -501,7 +593,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 'abc'; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); expect(impression.banner).to.exist; @@ -526,9 +618,9 @@ describe('IndexexchangeAdapter', function () { } }); - const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; - const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; + const expectedPageUrl = DEFAULT_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); }); @@ -540,10 +632,10 @@ describe('IndexexchangeAdapter', function () { } }); - const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); }); it('should not set first party or timeout if it is not present', function () { @@ -551,18 +643,18 @@ describe('IndexexchangeAdapter', function () { ix: {} }); - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); it('should not set first party or timeout if it is setConfig is not called', function () { - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); @@ -572,7 +664,7 @@ describe('IndexexchangeAdapter', function () { timeout: 500 } }); - const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; expect(requestWithTimeout.data.t).to.equal(500); }); @@ -583,14 +675,98 @@ describe('IndexexchangeAdapter', function () { timeout: '500' } }); - const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; expect(requestStringTimeout.data.t).to.be.undefined; }); + + it('request should contain both banner and video requests', function () { + const request = spec.buildRequests([DEFAULT_BANNER_VALID_BID[0], DEFAULT_VIDEO_VALID_BID[0]]); + + const bannerImp = JSON.parse(request[0].data.r).imp[0]; + expect(JSON.parse(request[0].data.v)).to.equal(BANNER_ENDPOINT_VERSION); + expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(bannerImp.banner).to.exist; + expect(bannerImp.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(bannerImp.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + + const videoImp = JSON.parse(request[1].data.r).imp[0]; + expect(JSON.parse(request[1].data.v)).to.equal(VIDEO_ENDPOINT_VERSION); + expect(videoImp.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(videoImp.video).to.exist; + expect(videoImp.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(videoImp.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + }); }); - describe('interpretResponseBanner', function () { - it('should get correct bid response', function () { + describe('buildRequestVideo', function () { + const request = spec.buildRequests(DEFAULT_VIDEO_VALID_BID, DEFAULT_OPTION); + const query = request[0].data; + + it('query object (version, siteID and request) should be correct', function () { + expect(query.v).to.equal(VIDEO_ENDPOINT_VERSION); + expect(query.s).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId); + expect(query.r).to.exist; + expect(query.ac).to.equal('j'); + expect(query.sd).to.equal(1); + }); + + it('impression should have correct format and value', function () { + const impression = JSON.parse(query.r).imp[0]; + const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + expect(impression.video.placement).to.exist; + expect(impression.video.placement).to.equal(1); + expect(impression.video.minduration).to.exist; + expect(impression.video.minduration).to.equal(0); + expect(impression.video.mimes).to.exist; + expect(impression.video.mimes[0]).to.equal('video/mp4'); + expect(impression.video.mimes[1]).to.equal('video/webm'); + + expect(impression.video.skippable).to.equal(false); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('impression should have correct format when mediaType is specified.', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'video'; + const requestBidFloor = spec.buildRequests([bid])[0]; + const impression = JSON.parse(requestBidFloor.data.r).imp[0]; + const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + expect(impression.video.placement).to.not.exist; + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('should set correct placement if context is outstream', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + bid.mediaTypes.video.context = 'outstream'; + const request = spec.buildRequests([bid])[0]; + const impression = JSON.parse(request.data.r).imp[0]; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.placement).to.exist; + expect(impression.video.placement).to.equal(4); + }); + }); + + describe('interpretResponse', function () { + it('should get correct bid response for banner ad', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -598,6 +774,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -610,7 +787,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); + const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -624,6 +801,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '-', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -636,8 +814,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); - expect(result[0]).to.deep.equal(expectedParse[0]); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); }); it('should set Japanese price correctly', function () { @@ -650,6 +827,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'JPY', ttl: 35, @@ -662,7 +840,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -676,6 +854,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -688,13 +867,38 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('should get correct bid response for video ad', function () { + const expectedParse = [ + { + requestId: '1a2b3c4e', + cpm: 1.1, + creativeId: '12346', + mediaType: 'video', + width: 640, + height: 480, + currency: 'USD', + ttl: 3600, + netRevenue: true, + dealId: undefined, + vastUrl: 'www.abcd.com/vast', + meta: { + networkId: 51, + brandId: 303326, + brandName: 'OECTB' + } + } + ]; + const result = spec.interpretResponse({ body: DEFAULT_VIDEO_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); it('bidrequest should have consent info if gdprApplies and consentString exist', function () { - const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -708,7 +912,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user).to.be.undefined; @@ -722,7 +926,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -731,7 +935,7 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user).to.be.undefined; @@ -740,10 +944,10 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have page if options is undefined', function () { const options = {}; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should not have page if options.refererInfo is an empty object', function () { @@ -751,10 +955,10 @@ describe('IndexexchangeAdapter', function () { refererInfo: {} }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should sent to secure endpoint if page url is secure', function () { @@ -764,10 +968,10 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.equal(options.refererInfo.referer); - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); }); }); From 356143915e648b1a71779ff25582c7769ec2b1cf Mon Sep 17 00:00:00 2001 From: Mirko Feddern Date: Tue, 25 Jun 2019 20:14:11 +0200 Subject: [PATCH 037/436] Add Outstream Renderer for Yieldlab Adapter (#3910) * Add Outstream Renderer * Fix playerSize overwrite Prebid is translating the playerSize to an array of arrays, so we have to return accordingly --- modules/yieldlabBidAdapter.js | 53 +++++++++++++++++++- modules/yieldlabBidAdapter.md | 2 +- test/spec/modules/yieldlabBidAdapter_spec.js | 17 +++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 1bbb3f11a2e..116f1aae0a8 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -2,11 +2,13 @@ import * as utils from '../src/utils' import { registerBidder } from '../src/adapters/bidderFactory' import find from 'core-js/library/fn/array/find' import { VIDEO, BANNER } from '../src/mediaTypes' +import { Renderer } from 'src/Renderer' const ENDPOINT = 'https://ad.yieldlab.net' const BIDDER_CODE = 'yieldlab' const BID_RESPONSE_TTL_SEC = 300 const CURRENCY_CODE = 'EUR' +const OUTSTREAMPLAYER_URL = 'https://ad2.movad.net/dynamic.ad?a=o193092&ma_loadEvent=ma-start-event' export const spec = { code: BIDDER_CODE, @@ -93,8 +95,23 @@ export const spec = { } if (isVideo(bidRequest)) { + const playersize = getPlayerSize(bidRequest) + if (playersize) { + bidResponse.width = playersize[0] + bidResponse.height = playersize[1] + } bidResponse.mediaType = VIDEO bidResponse.vastUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/${customsize[0]}x${customsize[1]}?ts=${timestamp}${extId}` + + if (isOutstream(bidRequest)) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: OUTSTREAMPLAYER_URL, + loaded: false + }) + renderer.setRender(outstreamRender) + bidResponse.renderer = renderer + } } bidResponses.push(bidResponse) @@ -106,13 +123,33 @@ export const spec = { /** * Is this a video format? - * @param {String} format + * @param {Object} format * @returns {Boolean} */ function isVideo (format) { return utils.deepAccess(format, 'mediaTypes.video') } +/** + * Is this an outstream context? + * @param {Object} format + * @returns {Boolean} + */ +function isOutstream (format) { + let context = utils.deepAccess(format, 'mediaTypes.video.context') + return (context === 'outstream') +} + +/** + * Gets optional player size + * @param {Object} format + * @returns {Array} + */ +function getPlayerSize (format) { + let playerSize = utils.deepAccess(format, 'mediaTypes.video.playerSize') + return (playerSize && utils.isArray(playerSize[0])) ? playerSize[0] : playerSize +} + /** * Expands a 'WxH' string as a 2-element [W, H] array * @param {String} size @@ -137,4 +174,18 @@ function createQueryString (obj) { return str.join('&') } +/** + * Handles an outstream response after the library is loaded + * @param {Object} bid + */ +function outstreamRender(bid) { + bid.renderer.push(() => { + window.ma_width = bid.width + window.ma_height = bid.height + window.ma_vastUrl = bid.vastUrl + window.ma_container = bid.adUnitCode + window.document.dispatchEvent(new Event('ma-start-event')) + }); +} + registerBidder(spec) diff --git a/modules/yieldlabBidAdapter.md b/modules/yieldlabBidAdapter.md index de93baf42ae..37897b83f12 100644 --- a/modules/yieldlabBidAdapter.md +++ b/modules/yieldlabBidAdapter.md @@ -34,7 +34,7 @@ Module that connects to Yieldlab's demand sources sizes: [[640, 480]], mediaTypes: { video: { - context: "instream" + context: "instream" // or "outstream" } }, bids: [{ diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index c2e12408cdd..c8709969e00 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -148,5 +148,22 @@ describe('yieldlabBidAdapter', function () { expect(result[0].vastUrl).to.include('https://ad.yieldlab.net/d/1111/2222/728x90?ts=') expect(result[0].vastUrl).to.include('&id=abc') }) + + it('should add renderer if outstream context', function () { + const OUTSTREAM_REQUEST = Object.assign({}, REQUEST, { + 'mediaTypes': { + 'video': { + 'playerSize': [[640, 480]], + 'context': 'outstream' + } + } + }) + const result = spec.interpretResponse({body: [RESPONSE]}, {validBidRequests: [OUTSTREAM_REQUEST]}) + + expect(result[0].renderer.id).to.equal('2d925f27f5079f') + expect(result[0].renderer.url).to.equal('https://ad2.movad.net/dynamic.ad?a=o193092&ma_loadEvent=ma-start-event') + expect(result[0].width).to.equal(640) + expect(result[0].height).to.equal(480) + }) }) }) From 41cee4d55adfb4f0e0f58862577757fa058529a9 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Tue, 25 Jun 2019 14:44:32 -0400 Subject: [PATCH 038/436] Standardized COPPA support (#3936) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * Send coppa flag on requests to OpenRTB from Prebid server * Support coppa flag being set in Prebid config * Add unit tests for deepSetValue util function --- modules/arteebeeBidAdapter.js | 2 +- modules/openxBidAdapter.js | 2 +- modules/openxoutstreamBidAdapter.js | 2 +- modules/prebidServerBidAdapter/index.js | 4 ++++ modules/rubiconBidAdapter.js | 8 ++++++++ test/spec/utils_spec.js | 23 +++++++++++++++++++++++ 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/arteebeeBidAdapter.js b/modules/arteebeeBidAdapter.js index ddf728a143e..74d5d5d3d52 100644 --- a/modules/arteebeeBidAdapter.js +++ b/modules/arteebeeBidAdapter.js @@ -96,7 +96,7 @@ function makeRtbRequest(req, bidderRequest) { 'tmax': config.getConfig('bidderTimeout') }; - if (req.params.coppa) { + if (config.getConfig('coppa') === true || req.params.coppa) { rtbReq.regs = {coppa: 1}; } diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 8236be8c2e5..ef60d6e1856 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -262,7 +262,7 @@ function buildOXBannerRequest(bids, bidderRequest) { queryParams.ns = 1; } - if (bids.some(bid => bid.params.coppa)) { + if (config.getConfig('coppa') === true || bids.some(bid => bid.params.coppa)) { queryParams.tfcd = 1; } diff --git a/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js index 42c7a3fff32..9011a949e7b 100644 --- a/modules/openxoutstreamBidAdapter.js +++ b/modules/openxoutstreamBidAdapter.js @@ -114,7 +114,7 @@ function buildOXBannerRequest(bid, bidderRequest) { queryParams.ns = 1; } - if (bid.params.coppa) { + if (config.getConfig('coppa') === true || bid.params.coppa) { queryParams.tfcd = 1; } diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 028f02d9662..4ac1bccaeda 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -580,6 +580,10 @@ const OPEN_RTB_PROTOCOL = { utils.deepSetValue(request, 'user.ext.consent', bidRequests[0].gdprConsent.consentString); } + if (getConfig('coppa') === true) { + utils.deepSetValue(request, 'regs.coppa', 1); + } + return request; }, diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index abeebd2e1b2..c3d0b48f14b 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -233,6 +233,10 @@ export const spec = { } } + if (config.getConfig('coppa') === true) { + utils.deepSetValue(request, 'regs.coppa', 1); + } + return { method: 'POST', url: VIDEO_ENDPOINT, @@ -434,6 +438,10 @@ export const spec = { const digitrustParams = _getDigiTrustQueryParams(bidRequest, 'FASTLANE'); Object.assign(data, digitrustParams); + if (config.getConfig('coppa') === true) { + data['coppa'] = 1; + } + return data; }, diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index df1c9b66b28..ff9b6ec2371 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -626,6 +626,29 @@ describe('Utils', function () { }); }); + describe('deepSetValue', function() { + it('should set existing properties at various depths', function() { + const testObj = { + prop: 'value', + nestedObj: { + nestedProp: 'nestedValue' + } + }; + utils.deepSetValue(testObj, 'prop', 'newValue'); + assert.equal(testObj.prop, 'newValue'); + utils.deepSetValue(testObj, 'nestedObj.nestedProp', 'newNestedValue'); + assert.equal(testObj.nestedObj.nestedProp, 'newNestedValue'); + }); + + it('should create object levels between top and bottom of given path if they do not exist', function() { + const testObj = {}; + utils.deepSetValue(testObj, 'level1.level2', 'value'); + assert.notEqual(testObj.level1, undefined); + assert.notEqual(testObj.level1.level2, undefined); + assert.equal(testObj.level1.level2, 'value'); + }); + }); + describe('createContentToExecuteExtScriptInFriendlyFrame', function () { it('should return empty string if url is not passed', function () { var output = utils.createContentToExecuteExtScriptInFriendlyFrame(); From 0ad5f97288de59b13d3ddaa719662f8e6100a4a3 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 25 Jun 2019 15:12:04 -0400 Subject: [PATCH 039/436] Adding privacy_supported flag (#3943) --- modules/appnexusBidAdapter.js | 4 ++++ test/spec/modules/appnexusBidAdapter_spec.js | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index e0ae19187b2..50c5a0e6f04 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -686,6 +686,10 @@ function buildNativeRequest(params) { request[requestKey].sizes = transformSizes(request[requestKey].sizes); } } + + if (requestKey === NATIVE_MAPPING.privacyLink) { + request.privacy_supported = true; + } }); return request; diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 9e37f6cbffb..e55e3e32029 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -432,7 +432,8 @@ describe('AppNexusAdapter', function () { likes: {required: true}, phone: {required: true}, price: {required: true}, - saleprice: {required: true} + saleprice: {required: true}, + privacy_supported: true }); }); From 17f8f3db7b3c5ab6e3f6a0797afb79756be774f0 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 25 Jun 2019 15:47:00 -0400 Subject: [PATCH 040/436] Prebid 2.21.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4e2985e1bd..6c0d2ace797 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.21.0-pre", + "version": "2.21.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From ea1b0c842a839a242190b51b6b3198a46dd57690 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 25 Jun 2019 16:06:35 -0400 Subject: [PATCH 041/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c0d2ace797..ae1d5ba514a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.21.0", + "version": "2.22.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 61abac3affec3eb1412ef16f797d3a9e433ecd17 Mon Sep 17 00:00:00 2001 From: Ryo Kato Date: Wed, 26 Jun 2019 21:44:07 +0900 Subject: [PATCH 042/436] Fix import paths in adapters (#3946) --- modules/bidglassBidAdapter.js | 4 ++-- modules/hpmdnetworkBidAdapter.js | 4 ++-- modules/open8BidAdapter.js | 2 +- modules/reloadBidAdapter.js | 4 ++-- modules/yieldlabBidAdapter.js | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/bidglassBidAdapter.js b/modules/bidglassBidAdapter.js index 1898d1220fa..f5991f7f3a5 100644 --- a/modules/bidglassBidAdapter.js +++ b/modules/bidglassBidAdapter.js @@ -1,6 +1,6 @@ -import * as utils from 'src/utils'; +import * as utils from '../src/utils'; // import {config} from 'src/config'; -import {registerBidder} from 'src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'bidglass'; diff --git a/modules/hpmdnetworkBidAdapter.js b/modules/hpmdnetworkBidAdapter.js index ad17caba7bc..b23d17a7bf3 100644 --- a/modules/hpmdnetworkBidAdapter.js +++ b/modules/hpmdnetworkBidAdapter.js @@ -1,5 +1,5 @@ -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'hpmdnetwork'; const BIDDER_CODE_ALIAS = 'hpmd'; diff --git a/modules/open8BidAdapter.js b/modules/open8BidAdapter.js index 3c2b94a528a..bac95f4499e 100644 --- a/modules/open8BidAdapter.js +++ b/modules/open8BidAdapter.js @@ -1,6 +1,6 @@ import { Renderer } from '../src/Renderer'; import {ajax} from '../src/ajax'; -import * as utils from 'src/utils'; +import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { VIDEO, BANNER } from '../src/mediaTypes'; diff --git a/modules/reloadBidAdapter.js b/modules/reloadBidAdapter.js index a50949825a9..a5f5ba43c60 100644 --- a/modules/reloadBidAdapter.js +++ b/modules/reloadBidAdapter.js @@ -1,11 +1,11 @@ import { BANNER } - from 'src/mediaTypes'; + from '../src/mediaTypes'; import { registerBidder } - from 'src/adapters/bidderFactory'; + from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'reload'; diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 116f1aae0a8..9af3de24cb1 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -2,7 +2,7 @@ import * as utils from '../src/utils' import { registerBidder } from '../src/adapters/bidderFactory' import find from 'core-js/library/fn/array/find' import { VIDEO, BANNER } from '../src/mediaTypes' -import { Renderer } from 'src/Renderer' +import { Renderer } from '../src/Renderer' const ENDPOINT = 'https://ad.yieldlab.net' const BIDDER_CODE = 'yieldlab' From f3d05809bc6370367e8baccc239737f702947129 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Wed, 26 Jun 2019 09:02:35 -0400 Subject: [PATCH 043/436] ozone adapter 2.1 - bug fix for multi bids + GDPR parameter handling (#3916) * bug fix for multi bids + GDPR parameter handling * Updated spec files and adapter files to remove references to ozoneData and more stringent GDPR checks. --- modules/ozoneBidAdapter.js | 67 +++-- modules/ozoneBidAdapter.md | 6 +- test/spec/modules/ozoneBidAdapter_spec.js | 300 ++++++++++++++++++---- 3 files changed, 304 insertions(+), 69 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index c5d9f16ef58..7ab69f1e37a 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -8,10 +8,10 @@ import { Renderer } from '../src/Renderer' const BIDDER_CODE = 'ozone'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; -const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js' - const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; -const OZONEVERSION = '2.0.0'; +const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js'; + +const OZONEVERSION = '2.1.1'; export const spec = { code: BIDDER_CODE, @@ -57,12 +57,6 @@ export const spec = { utils.logInfo('OZONE: OZONE BID ADAPTER VALIDATION FAILED : customParams should be renamed to customData'); return false; } - if (bid.params.hasOwnProperty('ozoneData')) { - if (typeof bid.params.ozoneData !== 'object') { - utils.logInfo('OZONE: OZONE BID ADAPTER VALIDATION FAILED : ozoneData is not an object'); - return false; - } - } if (bid.params.hasOwnProperty('lotameData')) { if (typeof bid.params.lotameData !== 'object') { utils.logInfo('OZONE: OZONE BID ADAPTER VALIDATION FAILED : lotameData is not an object'); @@ -90,18 +84,35 @@ export const spec = { let htmlParams = validBidRequests[0].params; // the html page config params will be included in each element let ozoneRequest = {}; // we only want to set specific properties on this, not validBidRequests[0].params delete ozoneRequest.test; // don't allow test to be set in the config - ONLY use $_GET['pbjs_debug'] - if (bidderRequest.gdprConsent) { + + if (bidderRequest && bidderRequest.gdprConsent) { utils.logInfo('OZONE: ADDING GDPR info'); ozoneRequest.regs = {}; ozoneRequest.regs.ext = {}; - ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; + ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; if (ozoneRequest.regs.ext.gdpr) { - ozoneRequest.user = {}; - ozoneRequest.user.ext = {'consent': bidderRequest.gdprConsent.consentString}; + ozoneRequest.user = ozoneRequest.user || {}; + if ( + bidderRequest.gdprConsent.vendorData && + bidderRequest.gdprConsent.vendorData.vendorConsents && + typeof bidderRequest.gdprConsent.consentString !== 'undefined' + ) { + utils.logInfo('OZONE: found all info we need for GDPR - will add info to request object'); + ozoneRequest.user.ext = {'consent': bidderRequest.gdprConsent.consentString}; + // are we able to make this request? + let vendorConsents = bidderRequest.gdprConsent.vendorData.vendorConsents; + let boolGdprConsentForOzone = vendorConsents[524]; + let arrGdprConsents = toFlatArray(bidderRequest.gdprConsent.vendorData.purposeConsents); + ozoneRequest.regs.ext.oz_con = boolGdprConsentForOzone ? 1 : 0; + ozoneRequest.regs.ext.gap = arrGdprConsents; + } + } else { + utils.logInfo('OZONE: **** Failed to find required info for GDPR for request object, even though bidderRequest.gdprConsent is TRUE ****'); } } else { - utils.logInfo('OZONE: WILL NOT ADD GDPR info'); + utils.logInfo('OZONE: WILL NOT ADD GDPR info; no bidderRequest.gdprConsent object was present.'); } + ozoneRequest.device = {'w': window.innerWidth, 'h': window.innerHeight}; let tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; @@ -157,9 +168,6 @@ export const spec = { if (ozoneBidRequest.params.hasOwnProperty('customData')) { obj.ext.ozone.customData = ozoneBidRequest.params.customData; } - if (ozoneBidRequest.params.hasOwnProperty('ozoneData')) { - obj.ext.ozone.ozoneData = ozoneBidRequest.params.ozoneData; - } if (ozoneBidRequest.params.hasOwnProperty('lotameData')) { obj.ext.ozone.lotameData = ozoneBidRequest.params.lotameData; } @@ -226,8 +234,8 @@ export const spec = { serverResponse.seatbid = injectAdIdsIntoAllBidResponses(serverResponse.seatbid); // we now make sure that each bid in the bidresponse has a unique (within page) adId attribute. for (let i = 0; i < serverResponse.seatbid.length; i++) { let sb = serverResponse.seatbid[i]; - const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[i]); for (let j = 0; j < sb.bid.length; j++) { + const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[j]); // there should be the same number of bids as requests, so index [j] should always exist. let thisBid = ozoneAddStandardProperties(sb.bid[j], defaultWidth, defaultHeight); // from https://github.com/prebid/Prebid.js/pull/1082 @@ -310,6 +318,13 @@ export function checkDeepArray(Arr) { } } export function defaultSize(thebidObj) { + if (!thebidObj) { + utils.logInfo('defaultSize received empty bid obj! going to return fixed default size'); + return { + 'defaultHeight': 250, + 'defaultWidth': 300 + }; + } const {sizes} = thebidObj; const returnObject = {}; returnObject.defaultWidth = checkDeepArray(sizes)[0]; @@ -499,5 +514,21 @@ function outstreamRender(bid) { window.ozoneVideo.outstreamRender(bid); } +/** + * convert {1: true, + 2: true, + 3: true, + 4: true, + 5: true} + to : [1,2,3,4,5] + * @param obj + */ +function toFlatArray(obj) { + let ret = []; + Object.keys(obj).forEach(function(key) { if (obj[key]) { ret.push(parseInt(key)); } }); + utils.logInfo('toFlatArray:', obj, 'returning', ret); + return ret; +} + registerBidder(spec); utils.logInfo('OZONE: ozoneBidAdapter ended'); diff --git a/modules/ozoneBidAdapter.md b/modules/ozoneBidAdapter.md index 89760697088..1fe5e681e25 100644 --- a/modules/ozoneBidAdapter.md +++ b/modules/ozoneBidAdapter.md @@ -36,8 +36,7 @@ adUnits = [{ publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ - customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ - ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ lotameData: {"key1": "value1", "key2": "value2"} /* optional JSON placeholder for passing Lotame DMP data */ } }] @@ -65,8 +64,7 @@ adUnits = [{ siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ customData: [{"settings": {}, "targeting": { "key": "value", "key2": ["value1", "value2"]}}] placementId: '0440440442', /* an ID used to identify the piece of inventory - required - for unruly test use 0440440442. */ - customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ - ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ lotameData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for passing Lotame DMP data */ video: { skippable: true, /* optional */ diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index b0f252d4469..e17d51804a1 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -18,7 +18,7 @@ var validBidRequests = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -45,7 +45,7 @@ var validBidRequestsNoSizes = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -59,7 +59,7 @@ var validBidRequestsWithBannerMediaType = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, mediaTypes: {banner: {sizes: [[300, 250], [300, 600]]}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -73,7 +73,7 @@ var validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo = [ bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream'}, native: {info: 'dummy data'}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -92,7 +92,7 @@ var validBidderRequest = { bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' }], @@ -100,6 +100,65 @@ var validBidderRequest = { start: 1536838908987, timeout: 3000 }; + +// bidder request with GDPR - change the values for testing: +// gdprConsent.gdprApplies (true/false) +// gdprConsent.vendorData.purposeConsents (make empty, make null, remove it) +// gdprConsent.vendorData.vendorConsents (remove 524, remove all, make the element null, remove it) +var bidderRequestWithFullGdpr = { + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + auctionStart: 1536838908986, + bidderCode: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + bids: [{ + adUnitCode: 'div-gpt-ad-1460505748561-0', + auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', + bidId: '2899ec066a91ff8', + bidRequestsCount: 1, + bidder: 'ozone', + bidderRequestId: '1c1586b27a1b5c8', + crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + sizes: [[300, 250], [300, 600]], + transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' + }], + doneCbCallCount: 1, + start: 1536838908987, + timeout: 3000, + gdprConsent: { + 'consentString': 'BOh7mtYOh7mtYAcABBENCU-AAAAncgPIXJiiAoao0PxBFkgCAC8ACIAAQAQQAAIAAAIAAAhBGAAAQAQAEQgAAAAAAABAAAAAAAAAAAAAAACAAAAAAAACgAAAAABAAAAQAAAAAAA', + 'vendorData': { + 'metadata': 'BOh7mtYOh7mtYAcABBENCU-AAAAncgPIXJiiAoao0PxBFkgCAC8ACIAAQAQQAAIAAAIAAAhBGAAAQAQAEQgAAAAAAABAAAAAAAAAAAAAAACAAAAAAAACgAAAAABAAAAQAAAAAAA', + 'gdprApplies': true, + 'hasGlobalScope': false, + 'cookieVersion': '1', + 'created': '2019-05-31T12:46:48.825', + 'lastUpdated': '2019-05-31T12:46:48.825', + 'cmpId': '28', + 'cmpVersion': '1', + 'consentLanguage': 'en', + 'consentScreen': '1', + 'vendorListVersion': 148, + 'maxVendorId': 631, + 'purposeConsents': { + '1': true, + '2': true, + '3': true, + '4': true, + '5': true + }, + 'vendorConsents': { + '468': true, + '522': true, + '524': true, /* 524 is ozone */ + '565': true, + '591': true + } + }, + 'gdprApplies': true + }, +}; + // make sure the impid matches the request bidId var validResponse = { 'body': { @@ -216,7 +275,97 @@ var validOutstreamResponse = { } }, 'headers': {} -} +}; +var validBidResponse1adWith2Bidders = { + 'body': { + 'id': '91221f96-b931-4acc-8f05-c2a1186fa5ac', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba', + 'impid': '2899ec066a91ff8', + 'price': 0.36754, + 'adm': '', + 'adid': '134928661', + 'adomain': [ + 'somecompany.com' + ], + 'iurl': 'https:\/\/ams1-ib.adnxs.com\/cr?id=134928661', + 'cid': '8825', + 'crid': '134928661', + 'cat': [ + 'IAB8-15', + 'IAB8-16', + 'IAB8-4', + 'IAB8-1', + 'IAB8-14', + 'IAB8-6', + 'IAB8-13', + 'IAB8-3', + 'IAB8-17', + 'IAB8-12', + 'IAB8-8', + 'IAB8-7', + 'IAB8-2', + 'IAB8-9', + 'IAB8', + 'IAB8-11' + ], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 14640, + 'auction_id': 1.8369641905139e+18, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'appnexus' + }, + { + 'bid': [ + { + 'id': '75665207-a1ca-49db-ba0e-a5e9c7d26f32', + 'impid': '37fff511779365a', + 'price': 1.046, + 'adm': '
removed
', + 'adomain': [ + 'kx.com' + ], + 'crid': '13005', + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + } + } + } + ], + 'seat': 'openx' + } + ], + 'ext': { + 'responsetimemillis': { + 'appnexus': 91, + 'openx': 109, + 'ozappnexus': 46, + 'ozbeeswax': 2, + 'pangaea': 91 + } + } + }, + 'headers': {} +}; describe('ozone Adapter', function () { describe('isBidRequestValid', function () { @@ -242,7 +391,6 @@ describe('ozone Adapter', function () { publisherId: '9876abcd12-3', siteId: '1234567890', customData: {'gender': 'bart', 'age': 'low'}, - ozoneData: {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, }, siteId: 1234567890 @@ -485,20 +633,6 @@ describe('ozone Adapter', function () { expect(spec.isBidRequestValid(xCustomParams)).to.equal(false); }); - var xBadOzoneData = { - bidder: BIDDER_CODE, - params: { - 'placementId': '1234567890', - 'publisherId': '9876abcd12-3', - 'ozoneData': 'this should be an object', - siteId: '1234567890' - } - }; - - it('should not validate ozoneData being sent', function () { - expect(spec.isBidRequestValid(xBadOzoneData)).to.equal(false); - }); - var xBadCustomData = { bidder: BIDDER_CODE, params: { @@ -508,10 +642,10 @@ describe('ozone Adapter', function () { siteId: '1234567890' } }; - it('should not validate ozoneData being sent', function () { expect(spec.isBidRequestValid(xBadCustomData)).to.equal(false); }); + var xBadLotame = { bidder: BIDDER_CODE, params: { @@ -521,7 +655,6 @@ describe('ozone Adapter', function () { siteId: '1234567890' } }; - it('should not validate lotameData being sent', function () { expect(spec.isBidRequestValid(xBadLotame)).to.equal(false); }); @@ -585,10 +718,21 @@ describe('ozone Adapter', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); expect(request.data).to.be.a('string'); var data = JSON.parse(request.data); - expect(data.imp[0].ext.ozone.ozoneData).to.be.an('object'); expect(data.imp[0].ext.ozone.lotameData).to.be.an('object'); expect(data.imp[0].ext.ozone.customData).to.be.an('object'); - expect(request).not.to.have.key('ozoneData'); + expect(request).not.to.have.key('lotameData'); + expect(request).not.to.have.key('customData'); + }); + + it('ignores ozoneData in & after version 2.1.1', function () { + let validBidRequestsWithOzoneData = validBidRequests; + validBidRequestsWithOzoneData[0].params.ozoneData = {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}; + const request = spec.buildRequests(validBidRequests, validBidderRequest); + expect(request.data).to.be.a('string'); + var data = JSON.parse(request.data); + expect(data.imp[0].ext.ozone.lotameData).to.be.an('object'); + expect(data.imp[0].ext.ozone.customData).to.be.an('object'); + expect(data.imp[0].ext.ozone.ozoneData).to.be.undefined; expect(request).not.to.have.key('lotameData'); expect(request).not.to.have.key('customData'); }); @@ -618,28 +762,6 @@ describe('ozone Adapter', function () { expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); }); - it('should add gdpr consent information to the request', function () { - let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; - let bidderRequest = { - 'bidderCode': 'ozone', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'gdprConsent': { - consentString: consentString, - gdprApplies: true - } - }; - bidderRequest.bids = validBidRequests; - - const request = spec.buildRequests(validBidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.user.ext).to.exist; - expect(payload.user.ext.consent).to.exist.and.to.equal(consentString); - expect(payload.regs.ext.gdpr).to.exist.and.to.equal(1); - }); - it('should be able to handle non-single requests', function () { config.setConfig({'ozone': {'singleRequest': false}}); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); @@ -648,6 +770,82 @@ describe('ozone Adapter', function () { // need to reset the singleRequest config flag: config.setConfig({'ozone': {'singleRequest': true}}); }); + + it('should add gdpr consent information to the request when ozone is true', function () { + let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA=='; + let bidderRequest = validBidderRequest; + bidderRequest.gdprConsent = { + consentString: consentString, + gdprApplies: true, + vendorData: { + vendorConsents: {524: true}, + purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + } + } + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.regs.ext.oz_con).to.exist.and.to.equal(1); + expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 2, 3, 4, 5]); + }); + + it('should add correct gdpr consent information to the request when user has accepted only some purpose consents', function () { + let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA=='; + let bidderRequest = validBidderRequest; + bidderRequest.gdprConsent = { + consentString: consentString, + gdprApplies: true, + vendorData: { + vendorConsents: {524: true}, + purposeConsents: {1: true, 4: true, 5: true} + } + } + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.regs.ext.oz_con).to.exist.and.to.equal(1); + expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 4, 5]); + }); + + it('should add gdpr consent information to the request when ozone is false', function () { + let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA=='; + let bidderRequest = validBidderRequest; + bidderRequest.gdprConsent = { + consentString: consentString, + gdprApplies: true, + vendorData: { + vendorConsents: {}, /* 524 is not present */ + purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + } + }; + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(1); + expect(payload.regs.ext.oz_con).to.exist.and.to.equal(0); + expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 2, 3, 4, 5]); + }); + + it('should set regs.ext.gdpr flag to 0 when gdprApplies is false', function () { + let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA=='; + let bidderRequest = validBidderRequest; + bidderRequest.gdprConsent = { + consentString: consentString, + gdprApplies: false, + vendorData: { + vendorConsents: {}, /* 524 is not present */ + purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + } + }; + + const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.regs.ext.gdpr).to.equal(0); + expect(payload.regs.ext.oz_con).to.be.undefined; + expect(payload.regs.ext.gap).to.be.undefined; + }); }); describe('interpretResponse', function () { @@ -673,11 +871,13 @@ describe('ozone Adapter', function () { const result = spec.interpretResponse(validResponse, request); expect(result.length).to.equal(1); }); + it('should fail ok if no seatbid in server response', function () { const result = spec.interpretResponse({}, {}); expect(result).to.be.an('array'); expect(result).to.be.empty; }); + it('should fail ok if seatbid is not an array', function () { const result = spec.interpretResponse({'body': {'seatbid': 'nothing_here'}}, {}); expect(result).to.be.an('array'); @@ -690,6 +890,12 @@ describe('ozone Adapter', function () { const bid = result[0]; expect(bid.renderer).to.be.an.instanceOf(Renderer); }); + + it('should correctly parse response where there are more bidders than ad slots', function () { + const request = spec.buildRequests(validBidRequests, validBidderRequest); + const result = spec.interpretResponse(validBidResponse1adWith2Bidders, request); + expect(result.length).to.equal(2); + }); }); describe('userSyncs', function () { From c5b179108026d8a997486341d061764fbdb5c7d6 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 27 Jun 2019 12:53:04 -0700 Subject: [PATCH 044/436] added cur to ortb --- modules/prebidServerBidAdapter/index.js | 8 +++++ .../modules/prebidServerBidAdapter_spec.js | 31 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 4ac1bccaeda..1d177464b9f 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -523,6 +523,14 @@ const OPEN_RTB_PROTOCOL = { request.ext.prebid = Object.assign(request.ext.prebid, _s2sConfig.extPrebid); } + /** + * @type {(string[]|undefined)} - OpenRTB property 'cur', currencies available for bids + */ + const adServerCur = config.getConfig('currency.adServerCurrency'); + if (Array.isArray(adServerCur) && adServerCur.length) { + request.cur = adServerCur.slice(); + } + _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index e2a3a5b111a..61db09b6451 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -831,7 +831,36 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); - }) + }); + + it('setting currency.adServerCurrency results in the openRTB JSON containing cur: ["AAA"]', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({ + currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, + s2sConfig: ortb2Config + }); + + const userIdBidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(parsedRequestBody.cur).to.deep.equal(['USD', 'GB', 'UK', 'AU']); + }); + + it('when currency.adServerCurrency is unset, the OpenRTB JSON should not contain cur', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; + config.setConfig({ + s2sConfig: ortb2Config + }); + + const userIdBidRequest = utils.deepClone(BID_REQUESTS); + adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); + + const parsedRequestBody = JSON.parse(requests[0].requestBody); + expect(typeof parsedRequestBody.cur).to.equal('undefined'); + }); it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { From 342cf82e5d014c0162a9df8f1b90e96d2a65f087 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Thu, 27 Jun 2019 13:10:52 -0700 Subject: [PATCH 045/436] Revert "added cur to ortb" This reverts commit 7b70c14750bac886ba7e34c2ccc3189392a1747b. --- modules/prebidServerBidAdapter/index.js | 8 ----- .../modules/prebidServerBidAdapter_spec.js | 31 +------------------ 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 1d177464b9f..4ac1bccaeda 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -523,14 +523,6 @@ const OPEN_RTB_PROTOCOL = { request.ext.prebid = Object.assign(request.ext.prebid, _s2sConfig.extPrebid); } - /** - * @type {(string[]|undefined)} - OpenRTB property 'cur', currencies available for bids - */ - const adServerCur = config.getConfig('currency.adServerCurrency'); - if (Array.isArray(adServerCur) && adServerCur.length) { - request.cur = adServerCur.slice(); - } - _appendSiteAppDevice(request); const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 61db09b6451..e2a3a5b111a 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -831,36 +831,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; ; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); - }); - - it('setting currency.adServerCurrency results in the openRTB JSON containing cur: ["AAA"]', function () { - let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; - config.setConfig({ - currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, - s2sConfig: ortb2Config - }); - - const userIdBidRequest = utils.deepClone(BID_REQUESTS); - adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); - - const parsedRequestBody = JSON.parse(requests[0].requestBody); - expect(parsedRequestBody.cur).to.deep.equal(['USD', 'GB', 'UK', 'AU']); - }); - - it('when currency.adServerCurrency is unset, the OpenRTB JSON should not contain cur', function () { - let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; - config.setConfig({ - s2sConfig: ortb2Config - }); - - const userIdBidRequest = utils.deepClone(BID_REQUESTS); - adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); - - const parsedRequestBody = JSON.parse(requests[0].requestBody); - expect(typeof parsedRequestBody.cur).to.equal('undefined'); - }); + }) it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { From ea75c068973348e9f8da37829343b60f7afcacb1 Mon Sep 17 00:00:00 2001 From: hdeodhar <35999856+hdeodhar@users.noreply.github.com> Date: Fri, 28 Jun 2019 16:04:00 +0100 Subject: [PATCH 046/436] Added 640x320 size (#3954) --- modules/rubiconBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index c3d0b48f14b..881ce480aef 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -83,6 +83,7 @@ var sizeMap = { 126: '200x600', 144: '980x600', 145: '980x150', + 156: '640x320', 159: '320x250', 179: '250x600', 195: '600x300', From 389d591ced506c4f11c77a982040bc25dada0dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deivydas=20=C5=A0abaras?= Date: Fri, 28 Jun 2019 19:45:04 +0100 Subject: [PATCH 047/436] OpenX should run only banner auction if it is multi format solution (#3940) --- modules/openxBidAdapter.js | 2 +- test/spec/modules/openxBidAdapter_spec.js | 35 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index ef60d6e1856..7be1023450f 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -75,7 +75,7 @@ export const spec = { }; function isVideoRequest(bidRequest) { - return utils.deepAccess(bidRequest, 'mediaTypes.video') || bidRequest.mediaType === VIDEO; + return (utils.deepAccess(bidRequest, 'mediaTypes.video') && !utils.deepAccess(bidRequest, 'mediaTypes.banner')) || bidRequest.mediaType === VIDEO; } function createBannerBidResponses(oxResponseObj, {bids, startTime}) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 0fda846faa1..cf8f4f8d62b 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -178,6 +178,41 @@ describe('OpenxAdapter', function () { }); }); + describe('when request is for a multiformat ad', function () { + describe('and request config uses mediaTypes video and banner', () => { + const multiformatBid = { + bidder: 'openx', + params: { + unit: '12345678', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + playerSize: [300, 250] + } + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + it('should return true multisize when required params found', function () { + expect(spec.isBidRequestValid(multiformatBid)).to.equal(true); + }); + + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { + const request = spec.buildRequests([multiformatBid]); + expect(request[0].url).to.equal(`//${multiformatBid.params.delDomain}${URLBASE}`); + expect(request[0].data.ph).to.be.undefined; + expect(request[0].method).to.equal('GET'); + }); + }); + }); + describe('when request is for a video ad', function () { describe('and request config uses mediaTypes', () => { const videoBidWithMediaTypes = { From fe07e0b2f693c8fb1abfe450a9e046d382ed6e2e Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Fri, 28 Jun 2019 12:21:42 -0700 Subject: [PATCH 048/436] Update creative.html (#3955) Updating for the new safe frame issue discovered, see https://github.com/prebid/prebid-universal-creative/pull/64/ for more details! --- integrationExamples/gpt/x-domain/creative.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integrationExamples/gpt/x-domain/creative.html b/integrationExamples/gpt/x-domain/creative.html index 3b0058f2ee8..a6981706227 100644 --- a/integrationExamples/gpt/x-domain/creative.html +++ b/integrationExamples/gpt/x-domain/creative.html @@ -2,10 +2,11 @@ // this script can be returned by an ad server delivering a cross domain iframe, into which the // creative will be rendered, e.g. DFP delivering a SafeFrame +let windowLocation = window.location; var urlParser = document.createElement('a'); urlParser.href = '%%PATTERN:url%%'; var publisherDomain = urlParser.protocol + '//' + urlParser.hostname; -var adServerDomain = urlParser.protocol + '//tpc.googlesyndication.com'; +var adServerDomain = windowLocation.protocol + '//tpc.googlesyndication.com'; function renderAd(ev) { var key = ev.message ? 'message' : 'data'; From 14c1fe46c91881f35025dfb8995a9b29692eee14 Mon Sep 17 00:00:00 2001 From: ix-certification Date: Mon, 1 Jul 2019 15:34:18 -0400 Subject: [PATCH 049/436] Revert addition of video support to IX adapter as it is still in testing (#3956) --- modules/ixBidAdapter.js | 366 +++++++++---------------- modules/ixBidAdapter.md | 128 +-------- test/spec/modules/ixBidAdapter_spec.js | 344 +++++------------------ 3 files changed, 210 insertions(+), 628 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index f26c5e413c5..c63b920dc93 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,75 +1,38 @@ import * as utils from '../src/utils'; -import { BANNER, VIDEO } from '../src/mediaTypes'; -import find from 'core-js/library/fn/array/find'; +import { BANNER } from '../src/mediaTypes'; import { config } from '../src/config'; import isArray from 'core-js/library/fn/array/is-array'; import isInteger from 'core-js/library/fn/number/is-integer'; import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'ix'; -const SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; -const INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; -const BANNER_ENDPOINT_VERSION = 7.2; -const VIDEO_ENDPOINT_VERSION = 8.1; - +const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; +const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; +const SUPPORTED_AD_TYPES = [BANNER]; +const ENDPOINT_VERSION = 7.2; const CENT_TO_DOLLAR_FACTOR = 100; -const BANNER_TIME_TO_LIVE = 35; -const VIDEO_TIME_TO_LIVE = 3600; // 1hr +const TIME_TO_LIVE = 35; const NET_REVENUE = true; const PRICE_TO_DOLLAR_FACTOR = { JPY: 1 }; /** - * Transform valid bid request config object to banner impression object that will be sent to ad server. + * Transform valid bid request config object to impression object that will be sent to ad server. * * @param {object} bid A valid bid request config object. * @return {object} A impression object that will be sent to ad server. */ function bidToBannerImp(bid) { - const imp = bidToImp(bid); + const imp = {}; + + imp.id = bid.bidId; imp.banner = {}; imp.banner.w = bid.params.size[0]; imp.banner.h = bid.params.size[1]; imp.banner.topframe = utils.inIframe() ? 0 : 1; - return imp; -} - -/** - * Transform valid bid request config object to video impression object that will be sent to ad server. - * - * @param {object} bid A valid bid request config object. - * @return {object} A impression object that will be sent to ad server. - */ -function bidToVideoImp(bid) { - const imp = bidToImp(bid); - - imp.video = utils.deepClone(bid.params.video) - imp.video.w = bid.params.size[0]; - imp.video.h = bid.params.size[1]; - - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (context) { - if (context === 'instream') { - imp.video.placement = 1; - } else if (context === 'outstream') { - imp.video.placement = 4; - } else { - utils.logWarn(`ix bidder params: video context '${context}' is not supported`); - } - } - - return imp; -} - -function bidToImp(bid) { - const imp = {}; - - imp.id = bid.bidId; - imp.ext = {}; imp.ext.siteID = bid.params.siteId; @@ -95,7 +58,7 @@ function bidToImp(bid) { * @param {string} currency Global currency in bid response. * @return {object} bid The parsed bid. */ -function parseBid(rawBid, currency, bidRequest) { +function parseBid(rawBid, currency) { const bid = {}; if (PRICE_TO_DOLLAR_FACTOR.hasOwnProperty(currency)) { @@ -105,27 +68,15 @@ function parseBid(rawBid, currency, bidRequest) { } bid.requestId = rawBid.impid; - + bid.width = rawBid.w; + bid.height = rawBid.h; + bid.ad = rawBid.adm; bid.dealId = utils.deepAccess(rawBid, 'ext.dealid'); + bid.ttl = TIME_TO_LIVE; bid.netRevenue = NET_REVENUE; bid.currency = currency; bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; - // in the event of a video - if (utils.deepAccess(rawBid, 'ext.vasturl')) { - bid.vastUrl = rawBid.ext.vasturl - bid.width = bidRequest.video.w; - bid.height = bidRequest.video.h; - bid.mediaType = VIDEO; - bid.ttl = VIDEO_TIME_TO_LIVE; - } else { - bid.ad = rawBid.adm; - bid.width = rawBid.w; - bid.height = rawBid.h; - bid.mediaType = BANNER; - bid.ttl = BANNER_TIME_TO_LIVE; - } - bid.meta = {}; bid.meta.networkId = utils.deepAccess(rawBid, 'ext.dspid'); bid.meta.brandId = utils.deepAccess(rawBid, 'ext.advbrandid'); @@ -182,143 +133,6 @@ function isValidBidFloorParams(bidFloor, bidFloorCur) { bidFloorCur.match(curRegex)); } -/** - * Finds the impression with the associated id. - * - * @param {*} id Id of the impression. - * @param {array} impressions List of impressions sent in the request. - * @return {object} The impression with the associated id. - */ -function getBidRequest(id, impressions) { - if (!id) { - return; - } - return find(impressions, imp => imp.id === id); -} - -/** - * Builds a request object to be sent to the ad server based on bid requests. - * - * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} bidderRequest An object containing other info like gdprConsent. - * @param {array} impressions List of impression objects describing the bids. - * @param {array} version Endpoint version denoting banner or video. - * @return {object} Info describing the request to the server. - * - */ -function buildRequest(validBidRequests, bidderRequest, impressions, version) { - const userEids = []; - - // Always start by assuming the protocol is HTTPS. This way, it will work - // whether the page protocol is HTTP or HTTPS. Then check if the page is - // actually HTTP.If we can guarantee it is, then, and only then, set protocol to - // HTTP. - let baseUrl = SECURE_BID_URL; - - // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded - // and if the data for the partner exist - if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { - let identityInfo = window.headertag.getIdentityInfo(); - if (identityInfo && typeof identityInfo === 'object') { - for (const partnerName in identityInfo) { - if (identityInfo.hasOwnProperty(partnerName)) { - let response = identityInfo[partnerName]; - if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { - userEids.push(response.data); - } - } - } - } - } - const r = {}; - - // Since bidderRequestId are the same for different bid request, just use the first one. - r.id = validBidRequests[0].bidderRequestId; - - r.imp = impressions; - - r.site = {}; - r.ext = {}; - r.ext.source = 'prebid'; - if (userEids.length > 0) { - r.user = {}; - r.user.eids = userEids; - } - - if (document.referrer && document.referrer !== '') { - r.site.ref = document.referrer; - } - - // Apply GDPR information to the request if GDPR is enabled. - if (bidderRequest) { - if (bidderRequest.gdprConsent) { - const gdprConsent = bidderRequest.gdprConsent; - - if (gdprConsent.hasOwnProperty('gdprApplies')) { - r.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - }; - } - - if (gdprConsent.hasOwnProperty('consentString')) { - r.user = r.user || {}; - r.user.ext = { - consent: gdprConsent.consentString || '' - }; - } - } - - if (bidderRequest.refererInfo) { - r.site.page = bidderRequest.refererInfo.referer; - - if (bidderRequest.refererInfo.referer && bidderRequest.refererInfo.referer.indexOf('https') !== 0) { - baseUrl = INSECURE_BID_URL; - } - } - } - - const payload = {}; - - // Parse additional runtime configs. - const otherIxConfig = config.getConfig('ix'); - if (otherIxConfig) { - // Append firstPartyData to r.site.page if firstPartyData exists. - if (typeof otherIxConfig.firstPartyData === 'object') { - const firstPartyData = otherIxConfig.firstPartyData; - let firstPartyString = '?'; - for (const key in firstPartyData) { - if (firstPartyData.hasOwnProperty(key)) { - firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; - } - } - firstPartyString = firstPartyString.slice(0, -1); - - r.site.page += firstPartyString; - } - - // Create t in payload if timeout is configured. - if (typeof otherIxConfig.timeout === 'number') { - payload.t = otherIxConfig.timeout; - } - } - - // Use the siteId in the first bid request as the main siteId. - payload.s = validBidRequests[0].params.siteId; - payload.v = version; - payload.r = JSON.stringify(r); - payload.ac = 'j'; - payload.sd = 1; - payload.nf = 1; - - return { - method: 'GET', - url: baseUrl, - data: payload - }; -} - export const spec = { code: BIDDER_CODE, @@ -332,25 +146,22 @@ export const spec = { */ isBidRequestValid: function (bid) { if (!isValidSize(bid.params.size)) { - utils.logError('ix bidder params: bid size has invalid format.'); return false; } if (!includesSize(bid.sizes, bid.params.size)) { - utils.logError('ix bidder params: bid size is not included in ad unit sizes.'); return false; } - if (bid.hasOwnProperty('mediaType') && !(utils.contains(SUPPORTED_AD_TYPES, bid.mediaType))) { + if (bid.hasOwnProperty('mediaType') && bid.mediaType !== 'banner') { return false; } - if (bid.hasOwnProperty('mediaTypes') && !(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || utils.deepAccess(bid, 'mediaTypes.video.playerSize'))) { + if (bid.hasOwnProperty('mediaTypes') && !utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { return false; } if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') { - utils.logError('ix bidder params: siteId must be string or number value.'); return false; } @@ -358,10 +169,8 @@ export const spec = { const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur'); if (hasBidFloor || hasBidFloorCur) { - if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) { - utils.logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.'); - return false; - } + return hasBidFloor && hasBidFloorCur && + isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur); } return true; @@ -371,49 +180,139 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} bidderRequest A object contains bids and other info like gdprConsent. + * @param {object} options A object contains bids and other info like gdprConsent. * @return {object} Info describing the request to the server. */ - buildRequests: function (validBidRequests, bidderRequest) { - let reqs = []; - let bannerImps = []; - let videoImps = []; + buildRequests: function (validBidRequests, options) { + const bannerImps = []; + const userEids = []; let validBidRequest = null; + let bannerImp = null; + + // Always start by assuming the protocol is HTTPS. This way, it will work + // whether the page protocol is HTTP or HTTPS. Then check if the page is + // actually HTTP.If we can guarantee it is, then, and only then, set protocol to + // HTTP. + let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { validBidRequest = validBidRequests[i]; - if (validBidRequest.mediaType === VIDEO || utils.deepAccess(validBidRequest, 'mediaTypes.video')) { - if (validBidRequest.mediaType === VIDEO || includesSize(validBidRequest.mediaTypes.video.playerSize, validBidRequest.params.size)) { - videoImps.push(bidToVideoImp(validBidRequest)); - } else { - utils.logError('Bid size is not included in video playerSize') + // Transform the bid request based on the banner format. + bannerImp = bidToBannerImp(validBidRequest); + bannerImps.push(bannerImp); + } + + // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded + // and if the data for the partner exist + if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { + let identityInfo = window.headertag.getIdentityInfo(); + if (identityInfo && typeof identityInfo === 'object') { + for (const partnerName in identityInfo) { + if (identityInfo.hasOwnProperty(partnerName)) { + let response = identityInfo[partnerName]; + if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { + userEids.push(response.data); + } + } } } - if (validBidRequest.mediaType === BANNER || utils.deepAccess(validBidRequest, 'mediaTypes.banner') || - (!validBidRequest.mediaType && !validBidRequest.mediaTypes)) { - bannerImps.push(bidToBannerImp(validBidRequest)); - } } + const r = {}; + + // Since bidderRequestId are the same for different bid request, just use the first one. + r.id = validBidRequests[0].bidderRequestId; + + r.imp = bannerImps; + r.site = {}; + r.ext = {}; + r.ext.source = 'prebid'; + if (userEids.length > 0) { + r.user = {}; + r.user.eids = userEids; + } + + if (document.referrer && document.referrer !== '') { + r.site.ref = document.referrer; + } + + // Apply GDPR information to the request if GDPR is enabled. + if (options) { + if (options.gdprConsent) { + const gdprConsent = options.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = r.user || {}; + r.user.ext = { + consent: gdprConsent.consentString || '' + }; + } + } + + if (options.refererInfo) { + r.site.page = options.refererInfo.referer; - if (bannerImps.length > 0) { - reqs.push(buildRequest(validBidRequests, bidderRequest, bannerImps, BANNER_ENDPOINT_VERSION)); + if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { + baseUrl = BANNER_INSECURE_BID_URL; + } + } } - if (videoImps.length > 0) { - reqs.push(buildRequest(validBidRequests, bidderRequest, videoImps, VIDEO_ENDPOINT_VERSION)); + + const payload = {}; + + // Parse additional runtime configs. + const otherIxConfig = config.getConfig('ix'); + if (otherIxConfig) { + // Append firstPartyData to r.site.page if firstPartyData exists. + if (typeof otherIxConfig.firstPartyData === 'object') { + const firstPartyData = otherIxConfig.firstPartyData; + let firstPartyString = '?'; + for (const key in firstPartyData) { + if (firstPartyData.hasOwnProperty(key)) { + firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; + } + } + firstPartyString = firstPartyString.slice(0, -1); + + r.site.page += firstPartyString; + } + + // Create t in payload if timeout is configured. + if (typeof otherIxConfig.timeout === 'number') { + payload.t = otherIxConfig.timeout; + } } - return reqs; + // Use the siteId in the first bid request as the main siteId. + payload.s = validBidRequests[0].params.siteId; + + payload.v = ENDPOINT_VERSION; + payload.r = JSON.stringify(r); + payload.ac = 'j'; + payload.sd = 1; + + return { + method: 'GET', + url: baseUrl, + data: payload + }; }, /** * Unpack the response from the server into a list of bids. * * @param {object} serverResponse A successful response from the server. - * @param {object} bidderRequest The bid request sent to the server. * @return {array} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse, bidderRequest) { + interpretResponse: function (serverResponse) { const bids = []; let bid = null; @@ -430,11 +329,8 @@ export const spec = { // Transform rawBid in bid response to the format that will be accepted by prebid. const innerBids = seatbid[i].bid; - let requestBid = JSON.parse(bidderRequest.data.r); - for (let j = 0; j < innerBids.length; j++) { - const bidRequest = getBidRequest(innerBids[j].impid, requestBid.imp); - bid = parseBid(innerBids[j], responseBody.cur, bidRequest); + bid = parseBid(innerBids[j], responseBody.cur); bids.push(bid); } } diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md index 7bd60ac413b..e99c42408f2 100644 --- a/modules/ixBidAdapter.md +++ b/modules/ixBidAdapter.md @@ -42,21 +42,16 @@ var adUnits = [{ ```javascript var adUnits = [{ // ... + mediaTypes: { banner: { sizes: [ [300, 250], [300, 600] ] - }, - video: { - context: 'instream', - playerSize: [ - [300, 250], - [300, 600] - ] } - }, + } + // ... }]; ``` @@ -66,7 +61,7 @@ var adUnits = [{ | Type | Support | --- | --- | Banner | Fully supported for all IX approved sizes. -| Video | Fully supported for all IX approved sizes. +| Video | Not supported. | Native | Not supported. # Bid Parameters @@ -81,17 +76,6 @@ object are detailed here. | siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` | size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`. Examples: `[300, 250]`, `[300, 600]`, `[728, 90]` -### Video - -| Key | Scope | Type | Description -| --- | --- | --- | --- -| siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` -| size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.video.playerSize`. Examples: `[300, 250]`, `[300, 600]` -| video | Required | Hash | The video object will serve as the properties of the video ad. You can create any field under the video object that is mentioned in the `OpenRTB Spec v2.5`. Some fields like `mimes, protocols, minduration, maxduration` are required. -| video.mimes | Required | String[] | Array list of content MIME types supported. Popular MIME types include, but are not limited to, `"video/x-ms- wmv"` for Windows Media and `"video/x-flv"` for Flash Video. -|video.minduration| Required | Integer | Minimum video ad duration in seconds. -|video.maxduration| Required | Integer | Maximum video ad duration in seconds. -|video.protocol / video.protocols| Required | Integer / Integer[] | Either a single protocol provided as an integer, or protocols provided as a list of integers. `2` - VAST 2.0, `3` - VAST 3.0, `5` - VAST 2.0 Wrapper, `6` - VAST 3.0 Wrapper Setup Guide @@ -100,9 +84,7 @@ Setup Guide Follow these steps to configure and add the IX module to your Prebid.js integration. -The examples in this guide assume the following starting configuration (you may remove banner or video, if either does not apply). - -In regards to video, `context` can either be `'instream'` or `'outstream'`. Note that `outstream` requires additional configuration on the adUnit. +The examples in this guide assume the following starting configuration: ```javascript var adUnits = [{ @@ -116,19 +98,6 @@ var adUnits = [{ } }, bids: [] -}, -{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'instream', - playerSize: [ - [300, 250], - [300, 600] - ] - } - }, - bids: [] }]; ``` @@ -150,9 +119,7 @@ bid objects under `adUnits[].bids`: Set `params.siteId` and `params.size` in each bid object to the values provided by your IX representative. -**Examples** - -**Banner:** +**Example** ```javascript var adUnits = [{ code: 'banner-div-a', @@ -179,94 +146,18 @@ var adUnits = [{ }] }]; ``` -**Video (Instream):** -```javascript -var adUnits = [{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'instream', - playerSize: [ - [300, 250], - [300, 600] - ] - } - }, - bids: [{ - bidder: 'ix', - params: { - siteId: '12345', - size: [300, 250], - video: { - skippable: false, - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0, - maxduration: 60, - protocols: [6] - } - } - }, { - bidder: 'ix', - params: { - siteId: '12345', - size: [300, 600], - video: { - // openrtb v2.5 compatible video obj - } - } - }] -}]; -``` + Please note that you can re-use the existing `siteId` within the same flex position. -**Video (Outstream):** -Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See http://prebid.org/dev-docs/show-outstream-video-ads.html for more information. -```javascript -var adUnits = [{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [[300, 250]] - } - }, - renderer: { - url: 'https://test.com/my-video-player.js', - render: function (bid) { - ... - } - }, - bids: [{ - bidder: 'ix', - params: { - siteId: '12345', - size: [300, 250], - video: { - skippable: false, - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0, - maxduration: 60, - protocols: [6] - } - } - }] -}]; -``` ##### 2. Include `ixBidAdapter` in your build process -When running the build command, include `ixBidAdapter` as a module, as well as `dfpAdServerVideo` if you require video support. +When running the build command, include `ixBidAdapter` as a module. ``` -gulp build --modules=ixBidAdapter,dfpAdServerVideo,fooBidAdapter,bazBidAdapter +gulp build --modules=ixBidAdapter,fooBidAdapter,bazBidAdapter ``` If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` @@ -275,7 +166,6 @@ to the top-level array in that file. ```json [ "ixBidAdapter", - "dfpAdServerVideo", "fooBidAdapter", "bazBidAdapter" ] diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 634d5041e6e..38e64e8d338 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -7,8 +7,7 @@ import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; - const VIDEO_ENDPOINT_VERSION = 8.1; - const BANNER_ENDPOINT_VERSION = 7.2; + const BIDDER_VERSION = 7.2; const DEFAULT_BANNER_VALID_BID = [ { @@ -30,37 +29,17 @@ describe('IndexexchangeAdapter', function () { auctionId: '1aa2bb3cc4dd' } ]; - - const DEFAULT_VIDEO_VALID_BID = [ - { - bidder: 'ix', - params: { - siteId: '456', - video: { - skippable: false, - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0 - }, - size: [400, 100] - }, - sizes: [[400, 100], [200, 400]], - mediaTypes: { - video: { - context: 'instream', - playerSize: [[400, 100], [200, 400]] - } - }, - adUnitCode: 'div-gpt-ad-1460505748562-0', - transactionId: '173f49a8-7549-4218-a23c-e7ba59b47230', - bidId: '1a2b3c4e', - bidderRequestId: '11a22b33c44e', - auctionId: '1aa2bb3cc4de' + const DEFAULT_BANNER_OPTION = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + }, + refererInfo: { + referer: 'http://www.prebid.org', + canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' } - ]; - + }; const DEFAULT_BANNER_BID_RESPONSE = { cur: 'USD', id: '11a22b33c44d', @@ -90,48 +69,6 @@ describe('IndexexchangeAdapter', function () { } ] }; - - const DEFAULT_VIDEO_BID_RESPONSE = { - cur: 'USD', - id: '1aa2bb3cc4de', - seatbid: [ - { - bid: [ - { - crid: '12346', - adomain: ['www.abcd.com'], - adid: '14851456', - impid: '1a2b3c4e', - cid: '3051267', - price: 110, - id: '2', - ext: { - vasturl: 'www.abcd.com/vast', - errorurl: 'www.abcd.com/error', - dspid: 51, - pricelevel: '_110', - advbrandid: 303326, - advbrand: 'OECTB' - } - } - ], - seat: '3971' - } - ] - }; - - const DEFAULT_OPTION = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - referer: 'http://www.prebid.org', - canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' - } - }; - const DEFAULT_IDENTITY_RESPONSE = { IdentityIp: { responsePending: false, @@ -146,31 +83,6 @@ describe('IndexexchangeAdapter', function () { } }; - const DEFAULT_BIDDER_REQUEST_DATA = { - ac: 'j', - r: JSON.stringify({ - id: '345', - imp: [ - { - id: '1a2b3c4e', - video: { - w: 640, - h: 480, - placement: 1 - } - } - ], - site: { - ref: 'http://ref.com/ref.html', - page: 'http://page.com' - }, - }), - s: '21', - sd: 1, - t: 1000, - v: 8.1 - }; - describe('inherited functions', function () { it('should exists and is a function', function () { const adapter = newBidder(spec); @@ -179,12 +91,11 @@ describe('IndexexchangeAdapter', function () { }); describe('isBidRequestValid', function () { - it('should return true when required params found for a banner or video ad', function () { + it('should return true when required params found for a banner ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); - expect(spec.isBidRequestValid(DEFAULT_VIDEO_VALID_BID[0])).to.equal(true); }); - it('should return true when optional bidFloor params found for an ad', function () { + it('should return true when optional params found for a banner ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -225,10 +136,10 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes is not banner or video', function () { + it('should return false when mediaTypes is not banner', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { - native: { + video: { sizes: [[300, 250]] } }; @@ -245,13 +156,19 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes.video does not have sizes', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - bid.mediaTypes = { - video: { - size: [[300, 250]] - } - }; + it('should return false when mediaType is not banner', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'banne'; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when mediaType is video', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'video'; + bid.sizes = [[300, 250]]; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -278,14 +195,6 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when mediaType is video', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - delete bid.mediaTypes; - bid.mediaType = 'video'; - bid.sizes = [[400, 100]]; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; @@ -323,7 +232,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return testCopy; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; }); afterEach(function() { @@ -434,7 +343,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return undefined; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -447,7 +356,7 @@ describe('IndexexchangeAdapter', function () { responsePending: true, data: {} } - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -457,7 +366,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending for all partners', function () { testCopy.IdentityIp.responsePending = true; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -468,7 +377,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending or not available for all partners', function () { testCopy.IdentityIp.responsePending = false; testCopy.IdentityIp.data = {}; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); query = request.data; const payload = JSON.parse(query.r); @@ -478,8 +387,8 @@ describe('IndexexchangeAdapter', function () { }); }); - describe('buildRequests', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + describe('buildRequestsBanner', function () { + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const requestUrl = request.url; const requestMethod = request.method; const query = request.data; @@ -487,7 +396,7 @@ describe('IndexexchangeAdapter', function () { const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); delete bidWithoutMediaType[0].mediaTypes; bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; - const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_OPTION)[0]; + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_BANNER_OPTION); const queryWithoutMediaType = requestWithoutMediaType.data; it('request should be made to IX endpoint with GET method', function () { @@ -496,12 +405,11 @@ describe('IndexexchangeAdapter', function () { }); it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(BANNER_ENDPOINT_VERSION); + expect(query.v).to.equal(BIDDER_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; expect(query.ac).to.equal('j'); expect(query.sd).to.equal(1); - expect(query.nf).to.equal(1); }); it('payload should have correct format and value', function () { @@ -509,7 +417,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -537,7 +445,7 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; - const requestBidFloor = spec.buildRequests([bid])[0]; + const requestBidFloor = spec.buildRequests([bid]); const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.bidfloor).to.equal(bid.params.bidFloor); @@ -549,7 +457,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -576,7 +484,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 50; - const requestBidFloor = spec.buildRequests([bid])[0]; + const requestBidFloor = spec.buildRequests([bid]); const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); @@ -593,7 +501,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 'abc'; - const requestBidFloor = spec.buildRequests([bid])[0]; + const requestBidFloor = spec.buildRequests([bid]); const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); expect(impression.banner).to.exist; @@ -618,9 +526,9 @@ describe('IndexexchangeAdapter', function () { } }); - const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; - const expectedPageUrl = DEFAULT_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; + const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); }); @@ -632,10 +540,10 @@ describe('IndexexchangeAdapter', function () { } }); - const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); }); it('should not set first party or timeout if it is not present', function () { @@ -643,18 +551,18 @@ describe('IndexexchangeAdapter', function () { ix: {} }); - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); it('should not set first party or timeout if it is setConfig is not called', function () { - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); @@ -664,7 +572,7 @@ describe('IndexexchangeAdapter', function () { timeout: 500 } }); - const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; + const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); expect(requestWithTimeout.data.t).to.equal(500); }); @@ -675,98 +583,14 @@ describe('IndexexchangeAdapter', function () { timeout: '500' } }); - const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; + const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); expect(requestStringTimeout.data.t).to.be.undefined; }); - - it('request should contain both banner and video requests', function () { - const request = spec.buildRequests([DEFAULT_BANNER_VALID_BID[0], DEFAULT_VIDEO_VALID_BID[0]]); - - const bannerImp = JSON.parse(request[0].data.r).imp[0]; - expect(JSON.parse(request[0].data.v)).to.equal(BANNER_ENDPOINT_VERSION); - expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); - expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); - expect(bannerImp.banner).to.exist; - expect(bannerImp.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); - expect(bannerImp.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); - - const videoImp = JSON.parse(request[1].data.r).imp[0]; - expect(JSON.parse(request[1].data.v)).to.equal(VIDEO_ENDPOINT_VERSION); - expect(videoImp.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(videoImp.video).to.exist; - expect(videoImp.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); - expect(videoImp.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); - }); }); - describe('buildRequestVideo', function () { - const request = spec.buildRequests(DEFAULT_VIDEO_VALID_BID, DEFAULT_OPTION); - const query = request[0].data; - - it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(VIDEO_ENDPOINT_VERSION); - expect(query.s).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId); - expect(query.r).to.exist; - expect(query.ac).to.equal('j'); - expect(query.sd).to.equal(1); - }); - - it('impression should have correct format and value', function () { - const impression = JSON.parse(query.r).imp[0]; - const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; - - expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(impression.video).to.exist; - expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); - expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); - expect(impression.video.placement).to.exist; - expect(impression.video.placement).to.equal(1); - expect(impression.video.minduration).to.exist; - expect(impression.video.minduration).to.equal(0); - expect(impression.video.mimes).to.exist; - expect(impression.video.mimes[0]).to.equal('video/mp4'); - expect(impression.video.mimes[1]).to.equal('video/webm'); - - expect(impression.video.skippable).to.equal(false); - expect(impression.ext).to.exist; - expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); - expect(impression.ext.sid).to.equal(sidValue); - }); - - it('impression should have correct format when mediaType is specified.', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - delete bid.mediaTypes; - bid.mediaType = 'video'; - const requestBidFloor = spec.buildRequests([bid])[0]; - const impression = JSON.parse(requestBidFloor.data.r).imp[0]; - const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; - - expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(impression.video).to.exist; - expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); - expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); - expect(impression.video.placement).to.not.exist; - expect(impression.ext).to.exist; - expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); - expect(impression.ext.sid).to.equal(sidValue); - }); - - it('should set correct placement if context is outstream', function () { - const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); - bid.mediaTypes.video.context = 'outstream'; - const request = spec.buildRequests([bid])[0]; - const impression = JSON.parse(request.data.r).imp[0]; - - expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); - expect(impression.video).to.exist; - expect(impression.video.placement).to.exist; - expect(impression.video.placement).to.equal(4); - }); - }); - - describe('interpretResponse', function () { - it('should get correct bid response for banner ad', function () { + describe('interpretResponseBanner', function () { + it('should get correct bid response', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -774,7 +598,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -787,7 +610,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -801,7 +624,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '-', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -814,7 +636,8 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: bidResponse }); + expect(result[0]).to.deep.equal(expectedParse[0]); }); it('should set Japanese price correctly', function () { @@ -827,7 +650,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'JPY', ttl: 35, @@ -840,7 +662,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: bidResponse }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -854,7 +676,6 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, - mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -867,38 +688,13 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); - expect(result[0]).to.deep.equal(expectedParse[0]); - }); - - it('should get correct bid response for video ad', function () { - const expectedParse = [ - { - requestId: '1a2b3c4e', - cpm: 1.1, - creativeId: '12346', - mediaType: 'video', - width: 640, - height: 480, - currency: 'USD', - ttl: 3600, - netRevenue: true, - dealId: undefined, - vastUrl: 'www.abcd.com/vast', - meta: { - networkId: 51, - brandId: 303326, - brandName: 'OECTB' - } - } - ]; - const result = spec.interpretResponse({ body: DEFAULT_VIDEO_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + const result = spec.interpretResponse({ body: bidResponse }); expect(result[0]).to.deep.equal(expectedParse[0]); }); it('bidrequest should have consent info if gdprApplies and consentString exist', function () { - const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -912,7 +708,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user).to.be.undefined; @@ -926,7 +722,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -935,7 +731,7 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); + const requestWithConsent = JSON.parse(validBidWithConsent.data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user).to.be.undefined; @@ -944,10 +740,10 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have page if options is undefined', function () { const options = {}; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should not have page if options.refererInfo is an empty object', function () { @@ -955,10 +751,10 @@ describe('IndexexchangeAdapter', function () { refererInfo: {} }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should sent to secure endpoint if page url is secure', function () { @@ -968,10 +764,10 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); expect(requestWithoutreferInfo.site.page).to.equal(options.refererInfo.referer); - expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); }); }); }); From e04c7fe8477c6f1cd29a10e8e216516cbaae0d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=9B=A8=E8=BB=92=20=D0=9F=D0=B5=D1=82=D1=80?= Date: Mon, 1 Jul 2019 23:38:29 +0200 Subject: [PATCH 050/436] Update emoteevBidAdapter.js (#3928) * Update emoteevBidAdapter.js Retrieve various data from the adapter configuration, and ensure they are properly formatted: - GDPR vendor consent - Metadata: intended to be used as an ID for external partners - Context: describe the context of the current ad unit Test coverage for emoteevBidAdapter.js: - Statements 94.83% - Branches 98.39% - Functions 100% - Lines 94.34% fixup! Update emoteevBidAdapter.js * remove pubCommonId import from emoteevBidAdapter * Format indentation * More detailed integration page example * Rename attribute to externalId * Simplify names of constants * Minor tweak * Update context value --- .../gpt/hello_world_emoteev.html | 145 +++++++++++------- modules/emoteevBidAdapter.js | 52 ++++++- modules/emoteevBidAdapter.md | 6 +- test/spec/modules/emoteevBidAdapter_spec.js | 139 +++++++++++++++-- 4 files changed, 263 insertions(+), 79 deletions(-) diff --git a/integrationExamples/gpt/hello_world_emoteev.html b/integrationExamples/gpt/hello_world_emoteev.html index 5a33e2d9701..f41ef308332 100644 --- a/integrationExamples/gpt/hello_world_emoteev.html +++ b/integrationExamples/gpt/hello_world_emoteev.html @@ -5,68 +5,99 @@ @@ -75,9 +106,9 @@

Basic Prebid.js Example

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

Prebid Video -- video.js

- + \ No newline at end of file diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 331a52c1ea0..09118bba1d2 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -10,9 +10,16 @@ describe('OneVideoBidAdapter', function () { beforeEach(function () { bidRequest = { + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, bidder: 'oneVideo', sizes: [640, 480], bidId: '30b3efwfwe1e', + adUnitCode: 'video1', params: { video: { playerWidth: 640, @@ -140,20 +147,23 @@ describe('OneVideoBidAdapter', function () { }); it('should return a valid bid response with just "adm"', function () { - const serverResponse = {seatbid: [{bid: [{id: 1, price: 6.01, adm: ''}]}], cur: 'USD'}; + const serverResponse = {seatbid: [{bid: [{id: 1, adid: 123, crid: 2, price: 6.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { requestId: bidRequest.bidId, bidderCode: spec.code, cpm: serverResponse.seatbid[0].bid[0].price, - creativeId: serverResponse.seatbid[0].bid[0].id, + adId: serverResponse.seatbid[0].bid[0].adid, + creativeId: serverResponse.seatbid[0].bid[0].crid, vastXml: serverResponse.seatbid[0].bid[0].adm, width: 640, height: 480, mediaType: 'video', currency: 'USD', ttl: 100, - netRevenue: true + netRevenue: true, + adUnitCode: bidRequest.adUnitCode, + renderer: (bidRequest.mediaTypes.video.context === 'outstream') ? newRenderer(bidRequest, bidResponse) : undefined, }; expect(bidResponse).to.deep.equal(o); }); From 83f76d98d115f40637c6add65de769a562fb5ad5 Mon Sep 17 00:00:00 2001 From: John Salis Date: Tue, 9 Jul 2019 13:06:31 -0400 Subject: [PATCH 059/436] Beachfront Adapter: Add secure protocol to endpoints (#3979) --- modules/beachfrontBidAdapter.js | 10 +++++----- test/spec/modules/beachfrontBidAdapter_spec.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index efc7dfeda8d..9e3da9dc7a1 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,12 +7,12 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.5'; +const ADAPTER_VERSION = '1.6'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; -export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; -export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; +export const VIDEO_ENDPOINT = 'https://reachms.bfmio.com/bid.json?exchange_id='; +export const BANNER_ENDPOINT = 'https://display.bfmio.com/prebid_display'; export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration']; @@ -123,12 +123,12 @@ export const spec = { } else if (syncOptions.iframeEnabled) { syncs.push({ type: 'iframe', - url: `//sync.bfmio.com/sync_iframe?ifg=1&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` + url: `https://sync.bfmio.com/sync_iframe?ifg=1&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` }); } else if (syncOptions.pixelEnabled) { syncs.push({ type: 'image', - url: `//sync.bfmio.com/syncb?pid=144&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` + url: `https://sync.bfmio.com/syncb?pid=144&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` }); } diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index f5890cb6475..c01a5a3a47c 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -719,7 +719,7 @@ describe('BeachfrontAdapter', function () { }); it('should return user syncs defined the bid response', function () { - const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncUrl = 'https://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; const syncOptions = { iframeEnabled: true, pixelEnabled: true @@ -737,7 +737,7 @@ describe('BeachfrontAdapter', function () { }); it('should not return user syncs if iframes are disabled', function () { - const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncUrl = 'https://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; const syncOptions = { iframeEnabled: false, pixelEnabled: true From f8c8fa0b4d2dac554abcaf27575f2e6aeaeb5704 Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Tue, 9 Jul 2019 20:06:59 +0300 Subject: [PATCH 060/436] TheMediaGrid Bid Adapter: use referrer from refererInfo (#3968) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter * Update The Grid Media Bidder Adapter to send refererInfo.referer as 'u' parameter in ad request --- modules/gridBidAdapter.js | 4 +++- test/spec/modules/gridBidAdapter_spec.js | 13 ++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index f02ec58fd68..ee1ae85e7ee 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -79,13 +79,15 @@ export const spec = { }); const payload = { - u: utils.getTopWindowUrl(), auids: auids.join(','), sizes: utils.getKeys(sizeMap).join(','), r: reqId }; if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + } if (bidderRequest.timeout) { payload.wtimeout = bidderRequest.timeout; } diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index 53560a9ac6f..d9bfb9e971a 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -47,6 +47,8 @@ describe('TheMediaGrid Adapter', function () { }); return res; } + const bidderRequest = {refererInfo: {referer: 'http://example.com'}}; + const encodedReferer = encodeURIComponent(bidderRequest.refererInfo.referer); let bidRequests = [ { 'bidder': 'grid', @@ -84,29 +86,30 @@ describe('TheMediaGrid Adapter', function () { ]; it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]]); + const request = spec.buildRequests([bidRequests[0]], bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('auids', '1'); expect(payload).to.have.property('sizes', '300x250,300x600'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); it('auids must not be duplicated', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('auids', '1,1,2'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); it('if gdprConsent is present payload must have gdpr params', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}, refererInfo: bidderRequest.refererInfo}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); + expect(payload).to.have.property('u', encodedReferer); expect(payload).to.have.property('gdpr_consent', 'AAA'); expect(payload).to.have.property('gdpr_applies', '1'); }); From 53f64e168f615aba8f6225154cdf9fff96bef391 Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Tue, 9 Jul 2019 22:46:54 +0530 Subject: [PATCH 061/436] PulsePoint adapter - Video support + userId module support (#3937) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * initial commit * Adding ortb params * Outstream fixes * Minor fixes * Test fixes * Minor refactor * Minor changes * Removing yarn lock file * battr fix and added test * PulsePoint adapter - user id module support (#10) * Making user sync pixels https as well. * fixing review comment --- modules/pulsepointBidAdapter.js | 146 ++++++++- modules/pulsepointBidAdapter.md | 54 +++- .../spec/modules/pulsepointBidAdapter_spec.js | 277 +++++++++++++++++- 3 files changed, 445 insertions(+), 32 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 206eb734495..9c0d67d9612 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -1,6 +1,7 @@ /* eslint dot-notation:0, quote-props:0 */ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { Renderer } from '../src/Renderer'; const NATIVE_DEFAULTS = { TITLE_LEN: 100, @@ -13,13 +14,14 @@ const NATIVE_DEFAULTS = { const DEFAULT_BID_TTL = 20; const DEFAULT_CURRENCY = 'USD'; const DEFAULT_NET_REVENUE = true; +const KNOWN_PARAMS = ['cp', 'ct', 'cf', 'video', 'battr', 'bcat', 'badv', 'bidfloor']; /** * PulsePoint Bid Adapter. * Contact: ExchangeTeam@pulsepoint.com * * Aliases - pulseLite and pulsepointLite are supported for backwards compatibility. - * Formats - Display/Native/Outstream formats supported. + * Formats - Display/Native/Video formats supported. * */ export const spec = { @@ -28,7 +30,7 @@ export const spec = { aliases: ['pulseLite', 'pulsepointLite'], - supportedMediaTypes: ['banner', 'native'], + supportedMediaTypes: ['banner', 'native', 'video'], isBidRequestValid: bid => ( !!(bid && bid.params && bid.params.cp && bid.params.ct) @@ -41,12 +43,16 @@ export const spec = { site: site(bidRequests), app: app(bidRequests), device: device(), + bcat: bidRequests[0].params.bcat, + badv: bidRequests[0].params.badv, + user: user(bidRequests[0], bidderRequest), + regs: regs(bidderRequest), }; - applyGdpr(bidderRequest, request); return { method: 'POST', - url: '//bid.contextweb.com/header/ortb', - data: JSON.stringify(request), + url: 'https://bid.contextweb.com/header/ortb?src=prebid', + data: request, + bidderRequest }; }, @@ -58,12 +64,12 @@ export const spec = { if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: '//bh.contextweb.com/visitormatch' + url: 'https://bh.contextweb.com/visitormatch' }]; } else if (syncOptions.pixelEnabled) { return [{ type: 'image', - url: '//bh.contextweb.com/visitormatch/prebid' + url: 'https://bh.contextweb.com/visitormatch/prebid' }]; } }, @@ -79,12 +85,13 @@ export const spec = { /** * Callback for bids, after the call to PulsePoint completes. */ -function bidResponseAvailable(bidRequest, bidResponse) { +function bidResponseAvailable(request, response) { const idToImpMap = {}; const idToBidMap = {}; - bidResponse = bidResponse.body + const idToSlotConfig = {}; + const bidResponse = response.body // extract the request bids and the response bids, keyed by impr-id - const ortbRequest = parse(bidRequest.data); + const ortbRequest = request.data; ortbRequest.imp.forEach(imp => { idToImpMap[imp.id] = imp; }); @@ -93,6 +100,11 @@ function bidResponseAvailable(bidRequest, bidResponse) { idToBidMap[bid.impid] = bid; })); } + if (request.bidderRequest) { + request.bidderRequest.bids.forEach(bid => { + idToSlotConfig[bid.bidId] = bid; + }); + } const bids = []; Object.keys(idToImpMap).forEach(id => { if (idToBidMap[id]) { @@ -109,6 +121,15 @@ function bidResponseAvailable(bidRequest, bidResponse) { if (idToImpMap[id]['native']) { bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); bid.mediaType = 'native'; + } else if (idToImpMap[id].video) { + // for outstream, a renderer is specified + if (idToSlotConfig[id] && utils.deepAccess(idToSlotConfig[id], 'mediaTypes.video.context') === 'outstream') { + bid.renderer = outstreamRenderer(utils.deepAccess(idToSlotConfig[id], 'renderer.options'), utils.deepAccess(idToBidMap[id], 'ext.outstream')); + } + bid.vastXml = idToBidMap[id].adm; + bid.mediaType = 'video'; + bid.width = idToBidMap[id].w; + bid.height = idToBidMap[id].h; } else { bid.ad = idToBidMap[id].adm; bid.width = idToImpMap[id].banner.w; @@ -138,6 +159,9 @@ function impression(slot) { banner: banner(slot), 'native': nativeImpression(slot), tagid: slot.params.ct.toString(), + video: video(slot), + bidfloor: slot.params.bidfloor, + ext: ext(slot), }; } @@ -146,12 +170,66 @@ function impression(slot) { */ function banner(slot) { const size = adSize(slot); - return slot.nativeParams ? null : { + return (slot.nativeParams || slot.params.video) ? null : { w: size[0], h: size[1], + battr: slot.params.battr, }; } +/** + * Produces an OpenRTB Video object for the slot given + */ +function video(slot) { + if (slot.params.video) { + return Object.assign({}, slot.params.video, {battr: slot.params.battr}); + } + return null; +} + +/** + * Unknown params are captured and sent on ext + */ +function ext(slot) { + const ext = {}; + const knownParamsMap = {}; + KNOWN_PARAMS.forEach(value => knownParamsMap[value] = 1); + Object.keys(slot.params).forEach(key => { + if (!knownParamsMap[key]) { + ext[key] = slot.params[key]; + } + }); + return Object.keys(ext).length > 0 ? { prebid: ext } : null; +} + +/** + * Sets up the renderer on the bid, for outstream bid responses. + */ +function outstreamRenderer(rendererOptions, outstreamExtOptions) { + const renderer = Renderer.install({ + url: outstreamExtOptions.rendererUrl, + config: { + defaultOptions: outstreamExtOptions.config, + rendererOptions, + type: outstreamExtOptions.type + }, + loaded: false, + }); + renderer.setRender((bid) => { + bid.renderer.push(() => { + const config = bid.renderer.getConfig(); + new window.PulsePointOutstreamRenderer().render({ + adUnitCode: bid.adUnitCode, + vastXml: bid.vastXml, + type: config.type, + defaultOptions: config.defaultOptions, + rendererOptions + }); + }); + }); + return renderer; +} + /** * Produces an OpenRTB Native object for the slot given. */ @@ -166,6 +244,7 @@ function nativeImpression(slot) { return { request: JSON.stringify({ assets }), ver: '1.1', + battr: slot.params.battr, }; } return null; @@ -312,13 +391,50 @@ function adSize(slot) { } /** - * Applies GDPR parameters to request. + * Handles the user level attributes and produces + * an openrtb User object. */ -function applyGdpr(bidderRequest, ortbRequest) { +function user(bidRequest, bidderRequest) { + var ext = {}; + if (bidderRequest) { + if (bidderRequest.gdprConsent) { + ext.consent = bidderRequest.gdprConsent.consentString; + } + } + if (bidRequest) { + if (bidRequest.userId) { + ext.eids = []; + addExternalUserId(ext.eids, bidRequest.userId.pubcid, 'pubcommon'); + addExternalUserId(ext.eids, bidRequest.userId.tdid, 'ttdid'); + addExternalUserId(ext.eids, utils.deepAccess(bidRequest.userId.digitrustid, 'data.id'), 'digitrust'); + addExternalUserId(ext.eids, bidRequest.userId.id5id, 'id5id'); + } + } + return { ext }; +} + +/** + * Produces external userid object in ortb 3.0 model. + */ +function addExternalUserId(eids, value, source) { + if (value) { + eids.push({ + source, + uids: [{ + id: value + }] + }); + } +} + +/** + * Produces the regulations ortb object + */ +function regs(bidderRequest) { if (bidderRequest && bidderRequest.gdprConsent) { - ortbRequest.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; - ortbRequest.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + return { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; } + return null; } /** diff --git a/modules/pulsepointBidAdapter.md b/modules/pulsepointBidAdapter.md index 1b119f0499f..36d4ef6cce5 100644 --- a/modules/pulsepointBidAdapter.md +++ b/modules/pulsepointBidAdapter.md @@ -7,7 +7,7 @@ # Description Connects to PulsePoint demand source to fetch bids. -Banner, Outstream and Native formats are supported. +Banner, Video and Native formats are supported. Please use ```pulsepoint``` as the bidder code. ```pulseLite``` and ```pulsepointLite``` aliases also supported as well. @@ -40,5 +40,57 @@ Please use ```pulsepoint``` as the bidder code. ct: 505642 } }] + },{ + code: 'outstream-div', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bids: [{ + bidder: 'pulsepoint', + params: { + cp: 512379, + ct: 505642, + video: { + h: 300, + w: 400, + minduration: 1, + maxduration: 210, + linearity: 1, + mimes: ["video/mp4", "video/ogg", "video/webm"], + pos: 3 + } + } + }], + renderer: { + options: { + text: "PulsePoint Outstream" + } + } + },{ + code: 'instream', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'pulsepoint', + params: { + cp: 512379, + ct: 694973, + video: { + battr: [1,3], + h: 300, + w: 400, + minduration: 1, + maxduration: 210, + protocols: [2,3,5] + } + } + }] }]; ``` diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index f40a270af11..1d22ca6eadc 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -1,8 +1,7 @@ /* eslint dot-notation:0, quote-props:0 */ import {expect} from 'chai'; import {spec} from 'modules/pulsepointBidAdapter'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; +import {deepClone, getTopWindowLocation} from 'src/utils'; describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ @@ -48,12 +47,103 @@ describe('PulsePoint Adapter Tests', function () { } } }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slotVideo', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + video: { + w: 400, + h: 300, + minduration: 5, + maxduration: 10, + startdelay: 0, + skip: 1, + minbitrate: 200, + protocols: [1, 2, 4] + } + } + }]; + const additionalParamsConfig = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + extra_key1: 'extra_val1', + extra_key2: 12345, + extra_key3: { + key1: 'val1', + key2: 23456, + }, + extra_key4: [1, 2, 3] + } + }]; + + const ortbParamsSlotConfig = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + bcat: ['IAB-1', 'IAB-20'], + battr: [1, 2, 3], + bidfloor: 1.5, + badv: ['cocacola.com', 'lays.com'] + } + }, { + placementCode: '/DfpAccount1/slotVideo', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + video: { + w: 400, + h: 300, + minduration: 5, + maxduration: 10, + }, + battr: [2, 3, 4], + bidfloor: 2.5, + } + }]; + + const outstreamSlotConfig = [{ + placementCode: '/DfpAccount1/slot1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + video: { + h: 300, + w: 400, + minduration: 1, + maxduration: 210, + linearity: 1, + } + }, + renderer: { + options: { + text: 'PulsePoint Outstream' + } + } + }]; it('Verify build request', function () { const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // site object expect(ortbRequest.site).to.not.equal(null); expect(ortbRequest.site.publisher).to.not.equal(null); @@ -78,7 +168,7 @@ describe('PulsePoint Adapter Tests', function () { it('Verify parse response', function () { const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; const ortbResponse = { seatbid: [{ bid: [{ @@ -107,7 +197,7 @@ describe('PulsePoint Adapter Tests', function () { it('Verify use ttl in ext', function () { const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; const ortbResponse = { seatbid: [{ bid: [{ @@ -139,9 +229,9 @@ describe('PulsePoint Adapter Tests', function () { it('Verify Native request', function () { const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // native impression expect(ortbRequest.imp[0].tagid).to.equal('t10000'); expect(ortbRequest.imp[0].banner).to.equal(null); @@ -177,9 +267,9 @@ describe('PulsePoint Adapter Tests', function () { it('Verify Native response', function () { const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; const nativeResponse = { 'native': { assets: [ @@ -229,8 +319,10 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verifies supported media types', function () { - expect(spec.supportedMediaTypes).to.have.lengthOf(2); + expect(spec.supportedMediaTypes).to.have.lengthOf(3); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); }); it('Verifies if bid request valid', function () { @@ -251,7 +343,7 @@ describe('PulsePoint Adapter Tests', function () { expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('iframe'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); + expect(options[0].url).to.equal('https://bh.contextweb.com/visitormatch'); }); it('Verifies image pixel sync', function () { @@ -259,12 +351,12 @@ describe('PulsePoint Adapter Tests', function () { expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); expect(options[0].type).to.equal('image'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); + expect(options[0].url).to.equal('https://bh.contextweb.com/visitormatch/prebid'); }); it('Verify app requests', function () { const request = spec.buildRequests(appSlotConfig); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // site object expect(ortbRequest.site).to.equal(null); expect(ortbRequest.app).to.not.be.null; @@ -283,9 +375,9 @@ describe('PulsePoint Adapter Tests', function () { } }; const request = spec.buildRequests(slotConfigs, bidderRequest); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); + const ortbRequest = request.data; // user object expect(ortbRequest.user).to.not.equal(null); expect(ortbRequest.user.ext).to.not.equal(null); @@ -295,4 +387,157 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.regs.ext).to.not.equal(null); expect(ortbRequest.regs.ext.gdpr).to.equal(1); }); + + it('Verify Video request', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.be.null; + expect(ortbRequest.imp[0].native).to.be.null; + expect(ortbRequest.imp[0].banner).to.be.null; + expect(ortbRequest.imp[0].video.w).to.equal(400); + expect(ortbRequest.imp[0].video.h).to.equal(300); + expect(ortbRequest.imp[0].video.minduration).to.equal(5); + expect(ortbRequest.imp[0].video.maxduration).to.equal(10); + expect(ortbRequest.imp[0].video.startdelay).to.equal(0); + expect(ortbRequest.imp[0].video.skip).to.equal(1); + expect(ortbRequest.imp[0].video.minbitrate).to.equal(200); + expect(ortbRequest.imp[0].video.protocols).to.eql([1, 2, 4]); + }); + + it('Verify Video response', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'http://pulsepoint.video.mp4' + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid['native']).to.be.undefined; + expect(bid.mediaType).to.equal('video'); + expect(bid.vastXml).to.equal(ortbResponse.seatbid[0].bid[0].adm); + }); + + it('Verify extra parameters', function () { + let request = spec.buildRequests(additionalParamsConfig); + let ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].ext).to.not.equal(null); + expect(ortbRequest.imp[0].ext.prebid).to.not.equal(null); + expect(ortbRequest.imp[0].ext.prebid).to.not.be.null; + expect(ortbRequest.imp[0].ext.prebid.extra_key1).to.equal('extra_val1'); + expect(ortbRequest.imp[0].ext.prebid.extra_key2).to.equal(12345); + expect(ortbRequest.imp[0].ext.prebid.extra_key3).to.not.be.null; + expect(ortbRequest.imp[0].ext.prebid.extra_key3.key1).to.equal('val1'); + expect(ortbRequest.imp[0].ext.prebid.extra_key3.key2).to.equal(23456); + expect(ortbRequest.imp[0].ext.prebid.extra_key4).to.eql([1, 2, 3]); + expect(Object.keys(ortbRequest.imp[0].ext.prebid)).to.eql(['extra_key1', 'extra_key2', 'extra_key3', 'extra_key4']); + // attempting with a configuration with no unknown params. + request = spec.buildRequests(outstreamSlotConfig); + ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].ext).to.equal(null); + }); + + it('Verify ortb parameters', function () { + const request = spec.buildRequests(ortbParamsSlotConfig); + const ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.bcat).to.eql(['IAB-1', 'IAB-20']); + expect(ortbRequest.badv).to.eql(['cocacola.com', 'lays.com']); + expect(ortbRequest.imp).to.have.lengthOf(2); + expect(ortbRequest.imp[0].bidfloor).to.equal(1.5); + expect(ortbRequest.imp[0].banner.battr).to.eql([1, 2, 3]); + expect(ortbRequest.imp[0].ext).to.be.null; + // slot 2 + expect(ortbRequest.imp[1].bidfloor).to.equal(2.5); + expect(ortbRequest.imp[1].video.battr).to.eql([2, 3, 4]); + expect(ortbRequest.imp[1].ext).to.be.null; + }); + + it('Verify outstream renderer', function () { + const request = spec.buildRequests(outstreamSlotConfig, {bids: [outstreamSlotConfig[0]]}); + const ortbRequest = request.data; + expect(ortbRequest).to.not.be.null; + expect(ortbRequest.imp[0]).to.not.be.null; + expect(ortbRequest.imp[0].video).to.not.be.null; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'http://pulsepoint.video.mp4', + ext: { + outstream: { + type: 'Inline', + config: { + text: 'ADVERTISEMENT', + skipaftersec: 5 + }, + rendererUrl: 'http://tag.contextweb.com/hb-outstr-renderer.js' + } + } + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.renderer).to.not.be.null; + expect(bid.renderer.url).to.equal('http://tag.contextweb.com/hb-outstr-renderer.js'); + expect(bid.renderer.getConfig()).to.not.be.null; + expect(bid.renderer.getConfig().defaultOptions).to.eql(ortbResponse.seatbid[0].bid[0].ext.outstream.config); + expect(bid.renderer.getConfig().rendererOptions).to.eql(outstreamSlotConfig[0].renderer.options); + expect(bid.renderer.getConfig().type).to.equal('Inline'); + }); + it('Verify common id parameters', function () { + const bidRequests = deepClone(slotConfigs); + bidRequests[0].userId = { + pubcid: 'userid_pubcid', + tdid: 'userid_ttd', + digitrustid: { + data: { + id: 'userid_digitrust', + keyv: 4, + privacy: {optout: false}, + producer: 'ABC', + version: 2 + } + } + }; + const request = spec.buildRequests(bidRequests); + expect(request).to.be.not.null; + const ortbRequest = request.data; + expect(request.data).to.be.not.null; + // user object + expect(ortbRequest.user).to.not.be.undefined; + expect(ortbRequest.user.ext).to.not.be.undefined; + expect(ortbRequest.user.ext.eids).to.not.be.undefined; + expect(ortbRequest.user.ext.eids).to.have.lengthOf(3); + expect(ortbRequest.user.ext.eids[0].source).to.equal('pubcommon'); + expect(ortbRequest.user.ext.eids[0].uids).to.have.lengthOf(1); + expect(ortbRequest.user.ext.eids[0].uids[0].id).to.equal('userid_pubcid'); + expect(ortbRequest.user.ext.eids[1].source).to.equal('ttdid'); + expect(ortbRequest.user.ext.eids[1].uids).to.have.lengthOf(1); + expect(ortbRequest.user.ext.eids[1].uids[0].id).to.equal('userid_ttd'); + expect(ortbRequest.user.ext.eids[2].source).to.equal('digitrust'); + expect(ortbRequest.user.ext.eids[2].uids).to.have.lengthOf(1); + expect(ortbRequest.user.ext.eids[2].uids[0].id).to.equal('userid_digitrust'); + }); }); From 66bb9fcdb400c84c98395b08b15e926855de148a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 9 Jul 2019 13:17:46 -0400 Subject: [PATCH 062/436] Criteo real time user sync (#3930) * add criteo rtus submodule and user id changes * update appnexus adapter to include criteo user id * updated to submodules pattern --- modules/.submodules.json | 3 +- modules/appnexusBidAdapter.js | 10 ++ modules/criteortusIdSystem.js | 105 +++++++++++++++++++ modules/userId/index.js | 13 ++- test/spec/modules/appnexusBidAdapter_spec.js | 16 +++ test/spec/modules/criteortusIdSystem_spec.js | 88 ++++++++++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 modules/criteortusIdSystem.js create mode 100644 test/spec/modules/criteortusIdSystem_spec.js diff --git a/modules/.submodules.json b/modules/.submodules.json index f321e075208..097fe4b1f3b 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -1,7 +1,8 @@ { "userId": [ "digiTrustIdSystem", - "id5IdSystem" + "id5IdSystem", + "criteortusIdSystem" ], "adpod": [ "freeWheelAdserverVideo" diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 50c5a0e6f04..67388848815 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -169,6 +169,16 @@ export const spec = { }); } + const rtusId = utils.deepAccess(bidRequests[0], `userId.criteortus.${BIDDER_CODE}.userid`); + if (rtusId) { + let tpuids = []; + tpuids.push({ + 'provider': 'criteo', + 'user_id': rtusId + }); + payload.tpuids = tpuids; + } + const request = formatRequest(payload, bidderRequest); return request; }, diff --git a/modules/criteortusIdSystem.js b/modules/criteortusIdSystem.js new file mode 100644 index 00000000000..02edf0ef06e --- /dev/null +++ b/modules/criteortusIdSystem.js @@ -0,0 +1,105 @@ +/** + * This module adds Criteo Real Time User Sync to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/criteortusIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils' +import { ajax } from '../src/ajax'; +import { submodule } from '../src/hook'; + +const key = '__pbjs_criteo_rtus'; + +/** @type {Submodule} */ +export const criteortusIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'criteortus', + /** + * decode the stored id value for passing to bid requests + * @function + * @returns {{criteortus:Object}} + */ + decode() { + let uid = utils.getCookie(key); + try { + uid = JSON.parse(uid); + return { 'criteortus': uid }; + } catch (error) { + utils.logError('Error in parsing criteo rtus data', error); + } + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @returns {function(callback:function)} + */ + getId(configParams) { + if (!configParams || !utils.isPlainObject(configParams.clientIdentifier)) { + utils.logError('User ID - Criteo rtus requires client identifier to be defined'); + return; + } + + let uid = utils.getCookie(key); + if (uid) { + return uid; + } else { + let userIds = {}; + return function(callback) { + let bidders = Object.keys(configParams.clientIdentifier); + + function afterAllResponses() { + // criteo rtus user id expires in 1 hour + const expiresStr = (new Date(Date.now() + (60 * 60 * 1000))).toUTCString(); + utils.setCookie(key, JSON.stringify(userIds), expiresStr); + callback(userIds); + } + + const onResponse = utils.delayExecution(afterAllResponses, bidders.length); + + bidders.forEach((bidder) => { + let url = `https://gum.criteo.com/sync?c=${configParams.clientIdentifier[bidder]}&r=3`; + const getSuccessHandler = (bidder) => { + return function onSuccess(response) { + if (response) { + try { + response = JSON.parse(response); + userIds[bidder] = response; + onResponse(); + } catch (error) { + utils.logError(error); + } + } + } + } + + const getFailureHandler = (bidder) => { + return function onFailure(error) { + utils.logError(`Criteo RTUS server call failed for ${bidder}`, error); + onResponse(); + } + } + + ajax( + url, + { + success: getSuccessHandler(bidder), + error: getFailureHandler(bidder) + }, + undefined, + Object.assign({ + method: 'GET', + withCredentials: true + }) + ); + }) + } + } + } +}; + +submodule('userId', criteortusIdSubmodule); diff --git a/modules/userId/index.js b/modules/userId/index.js index 2091a6a763a..e83258a4e02 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -186,7 +186,9 @@ function processSubmoduleCallbacks(submodules) { submodule.callback = undefined; // if valid, id data should be saved to cookie/html storage if (idObj) { - setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); + if (submodule.config.storage) { + setStoredValue(submodule.config.storage, idObj, submodule.config.storage.expires); + } // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.submodule.decode(idObj); } else { @@ -299,6 +301,13 @@ function initSubmodules(submodules, consentData) { } else if (submodule.config.value) { // cache decoded value (this is copied to every adUnit bid) submodule.idObj = submodule.config.value; + } else { + const result = submodule.submodule.getId(submodule.config.params, consentData); + if (typeof result === 'function') { + submodule.callback = result; + } else { + submodule.idObj = submodule.submodule.decode(); + } } carry.push(submodule); return carry; @@ -332,6 +341,8 @@ function getValidSubmoduleConfigs(configRegistry, submoduleRegistry, activeStora carry.push(config); } else if (utils.isPlainObject(config.value)) { carry.push(config); + } else if (!config.storage && !config.value) { + carry.push(config); } return carry; }, []); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index e55e3e32029..30d2dc08159 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -614,6 +614,22 @@ describe('AppNexusAdapter', function () { rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') }); }); + + it('should populate tpids array when userId is available', function () { + const bidRequest = Object.assign({}, bidRequests[0], { + userId: { + criteortus: { + appnexus: { + userid: 'sample-userid' + } + } + } + }); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tpuids).to.deep.equal([{provider: 'criteo', user_id: 'sample-userid'}]); + }); }) describe('interpretResponse', function () { diff --git a/test/spec/modules/criteortusIdSystem_spec.js b/test/spec/modules/criteortusIdSystem_spec.js new file mode 100644 index 00000000000..578f14d066d --- /dev/null +++ b/test/spec/modules/criteortusIdSystem_spec.js @@ -0,0 +1,88 @@ +import { criteortusIdSubmodule } from 'modules/criteortusIdSystem'; +import * as utils from 'src/utils'; + +describe('Criteo RTUS', function() { + let xhr; + let requests; + let getCookieStub; + let logErrorStub; + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + getCookieStub = sinon.stub(utils, 'getCookie'); + logErrorStub = sinon.stub(utils, 'logError'); + }); + + afterEach(function () { + xhr.restore(); + getCookieStub.restore(); + logErrorStub.restore(); + }); + + it('should log error when configParams are not passed', function() { + criteortusIdSubmodule.getId(); + expect(logErrorStub.calledOnce).to.be.true; + }) + + it('should call criteo endpoint to get user id', function() { + getCookieStub.returns(null); + let configParams = { + clientIdentifier: { + 'sampleBidder': 1 + } + } + + let response = { 'status': 'ok', 'userid': 'sample-userid' } + let callBackSpy = sinon.spy(); + let submoduleCallback = criteortusIdSubmodule.getId(configParams); + submoduleCallback(callBackSpy); + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify(response) + ); + expect(callBackSpy.calledOnce).to.be.true; + expect(callBackSpy.calledWith({'sampleBidder': response})).to.be.true; + }) + + it('should get uid from cookie and not call endpoint', function() { + let response = {'appnexus': {'status': 'ok', 'userid': 'sample-userid'}} + getCookieStub.returns(JSON.stringify(response)); + let configParams = { + clientIdentifier: { + 'sampleBidder': 1 + } + } + let uid = criteortusIdSubmodule.getId(configParams); + expect(requests.length).to.equal(0); + }) + + it('should call criteo endpoint for multiple bidders', function() { + getCookieStub.returns(null); + let configParams = { + clientIdentifier: { + 'sampleBidder': 1, + 'sampleBidder2': 2 + } + } + + let response = { 'status': 'ok', 'userid': 'sample-userid' } + let callBackSpy = sinon.spy(); + let submoduleCallback = criteortusIdSubmodule.getId(configParams); + submoduleCallback(callBackSpy); + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify(response) + ); + expect(callBackSpy.calledOnce).to.be.false; + requests[1].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify(response) + ); + expect(callBackSpy.calledOnce).to.be.true; + }) +}); From 0315aa85d6ef72ff1ad9cd3b077f4fd77eba9d90 Mon Sep 17 00:00:00 2001 From: Samuel Adu Date: Tue, 9 Jul 2019 18:20:22 +0100 Subject: [PATCH 063/436] AOL Adapter: Perform requests over https by default. (#3957) * Perform requests over https by default. Preserve insecure requests only if explicitly specified via the server override parameter (to aid with testing). * Slight refactor. --- modules/aolBidAdapter.js | 21 ++++++---- test/spec/modules/aolBidAdapter_spec.js | 56 ++++++++++++++++++------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 5b8a76db4fc..c065828c10d 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -29,17 +29,18 @@ const SYNC_TYPES = { } }; -const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; -const nexageBaseApiTemplate = template`//${'host'}/bidRequest?`; +const pubapiTemplate = template`${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; +const nexageBaseApiTemplate = template`${'host'}/bidRequest?`; const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'dynamicParams'}`; const MP_SERVER_MAP = { us: 'adserver-us.adtech.advertising.com', eu: 'adserver-eu.adtech.advertising.com', as: 'adserver-as.adtech.advertising.com' }; -const NEXAGE_SERVER = 'hb.nexage.com'; +const NEXAGE_SERVER = 'c2shb.ssp.yahoo.com'; const ONE_DISPLAY_TTL = 60; const ONE_MOBILE_TTL = 3600; +const DEFAULT_PROTO = 'https'; const NUMERIC_VALUES = { TRUE: 1, @@ -198,7 +199,7 @@ export const spec = { // Set region param, used by AOL analytics. params.region = regionParam; - return pubapiTemplate({ + return this.applyProtocol(pubapiTemplate({ host: server, network: params.network, placement: parseInt(params.placement), @@ -207,7 +208,7 @@ export const spec = { alias: params.alias || utils.getUniqueIdentifierStr(), misc: new Date().getTime(), // cache busting dynamicParams: this.formatMarketplaceDynamicParams(params, consentData) - }); + })); }, buildOneMobileGetUrl(bid, consentData) { let {dcn, pos, ext} = bid.params; @@ -219,9 +220,15 @@ export const spec = { return nexageApi; }, buildOneMobileBaseUrl(bid) { - return nexageBaseApiTemplate({ + return this.applyProtocol(nexageBaseApiTemplate({ host: bid.params.host || NEXAGE_SERVER - }); + })); + }, + applyProtocol(url) { + if (/^https?:\/\//i.test(url)) { + return url; + } + return (url.indexOf('//') === 0) ? `${DEFAULT_PROTO}:${url}` : `${DEFAULT_PROTO}://${url}`; }, formatMarketplaceDynamicParams(params = {}, consentData) { let queryParams = {}; diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index 7817c939b69..8386c2c2462 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -76,8 +76,8 @@ let getPixels = () => { }; describe('AolAdapter', function () { - const MARKETPLACE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; - const NEXAGE_URL = '//hb.nexage.com/bidRequest?'; + const MARKETPLACE_URL = 'https://adserver-us.adtech.advertising.com/pubapi/3.0/'; + const NEXAGE_URL = 'https://c2shb.ssp.yahoo.com/bidRequest?'; const ONE_DISPLAY_TTL = 60; const ONE_MOBILE_TTL = 3600; @@ -152,7 +152,7 @@ describe('AolAdapter', function () { it('should return request for Marketplace endpoint', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return request for Marketplace via onedisplay bidder code', function () { @@ -164,7 +164,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return Marketplace request via onedisplay bidder code when' + @@ -178,7 +178,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return Marketplace request via onedisplay bidder code when' + @@ -192,7 +192,7 @@ describe('AolAdapter', function () { }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should not resolve endpoint for onedisplay bidder code ' + @@ -218,10 +218,37 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); }); - it('should return Marketplace URL for eu region when server option is present', function () { + it('should return insecure MP URL if insecure server option is present', function () { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + server: 'http://adserver-eu.adtech.advertising.com' + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url.indexOf('http://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); + }); + + it('should return a secure MP URL if relative proto server option is present', function () { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + server: '//adserver-eu.adtech.advertising.com' + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); + }); + + it('should return a secure MP URL when server option without protocol is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -230,7 +257,8 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) + .to.equal(0); }); it('should return default Marketplace URL in case of unknown region config option', function () { @@ -242,7 +270,7 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(MARKETPLACE_URL); + expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); }); it('should return url with pubapi bid option', function () { @@ -358,13 +386,13 @@ describe('AolAdapter', function () { it('should return One Mobile url with different host when host option is present', function () { let bidParams = Object.assign({ - host: 'qa-hb.nexage.com' + host: 'http://qa-hb.nexage.com' }, getNexageGetBidParams()); let bidRequest = createCustomBidRequest({ params: bidParams }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('qa-hb.nexage.com/bidRequest?'); + expect(request.url).to.contain('http://qa-hb.nexage.com/bidRequest?'); }); it('should return One Mobile url when One Mobile and Marketplace params are present', function () { @@ -431,7 +459,7 @@ describe('AolAdapter', function () { } }); let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + + expect(request.url).to.equal('https://c2shb.ssp.yahoo.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); }); @@ -455,7 +483,7 @@ describe('AolAdapter', function () { }); it('should not return request object for One Mobile POST endpoint' + - 'if required parameterers are missed', () => { + 'if required parameters are missed', () => { let bidRequest = createCustomBidRequest({ params: { imp: [] From 22866a6eb9374bf33a3361b361498ca6e4fe3d1c Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Tue, 9 Jul 2019 13:21:06 -0400 Subject: [PATCH 064/436] Rubicon add meta fields to bids (#3947) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * Added meta fields to bids in response from Rubicon exchange --- modules/rubiconBidAdapter.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 881ce480aef..b4b8e98e393 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -557,6 +557,9 @@ export const spec = { netRevenue: config.getConfig('rubicon.netRevenue') || false, rubicon: { advertiserId: ad.advertiser, networkId: ad.network + }, + meta: { + advertiserId: ad.advertiser, networkId: ad.network } }; From 1cab1ee0f5a30595791c1113de04e604ecedbc76 Mon Sep 17 00:00:00 2001 From: John Rosendahl Date: Tue, 9 Jul 2019 11:25:55 -0600 Subject: [PATCH 065/436] Sovrn Analytics : Calculate highest bid based on ad unit (#3973) --- modules/sovrnAnalyticsAdapter.js | 11 ++- .../modules/sovrnAnalyticsAdapter_spec.js | 76 ++++++++++++++++++- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/modules/sovrnAnalyticsAdapter.js b/modules/sovrnAnalyticsAdapter.js index 3113f7ff5af..bb9051b5a8a 100644 --- a/modules/sovrnAnalyticsAdapter.js +++ b/modules/sovrnAnalyticsAdapter.js @@ -211,15 +211,18 @@ class AuctionData { * Sends the auction to the the ingest server */ send() { - let maxbid = {cpm: 0} + let maxBids = {} this.auction.requests.forEach(request => { request.bids.forEach(bid => { - if (bid.cpm > maxbid.cpm) { - maxbid = bid + maxBids[bid.adUnitCode] = maxBids[bid.adUnitCode] || {cpm: 0} + if (bid.cpm > maxBids[bid.adUnitCode].cpm) { + maxBids[bid.adUnitCode] = bid } }) }) - maxbid.isAuctionWinner = true + Object.keys(maxBids).forEach(unit => { + maxBids[unit].isAuctionWinner = true + }) this.auction.ts = utils.timestamp() ajax( pbaUrl, diff --git a/test/spec/modules/sovrnAnalyticsAdapter_spec.js b/test/spec/modules/sovrnAnalyticsAdapter_spec.js index 404833f0177..299e22ca790 100644 --- a/test/spec/modules/sovrnAnalyticsAdapter_spec.js +++ b/test/spec/modules/sovrnAnalyticsAdapter_spec.js @@ -27,8 +27,11 @@ let auctionInit = { let bidderCode = 'sovrn'; let bidderRequestId = '123bri'; let adUnitCode = 'div'; +let adUnitCode2 = 'div2'; let bidId = 'bidid'; +let bidId2 = 'bidid2'; let tId = '7aafa3ee-a80a-46d7-a4a0-cbcba463d97a'; +let tId2 = '99dca3ee-a80a-46d7-a4a0-cbcba463d97e'; let bidRequested = { auctionStart: auctionStartTimestamp, bidderCode: bidderCode, @@ -42,6 +45,15 @@ let bidRequested = { sizes: [[300, 250]], startTime: auctionStartTimestamp + 100, transactionId: tId + }, + { + adUnitCode: adUnitCode2, + bidId: bidId2, + bidder: bidderCode, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 100, + transactionId: tId2 } ], doneCbCallCount: 1, @@ -83,6 +95,42 @@ let bidResponse = { }, status: 'rendered' }; + +let bidResponse2 = { + bidderCode: bidderCode, + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '9999e27a5752fb', + mediaType: 'banner', + source: 'client', + requestId: bidId2, + cpm: 0.12, + creativeId: 'cridprebidrtb', + dealId: null, + currency: 'USD', + netRevenue: true, + ad: '
divvy mcdiv
', + ttl: 60000, + responseTimestamp: auctionStartTimestamp + 150, + requestTimestamp: auctionStartTimestamp + 100, + bidder: bidderCode, + adUnitCode: adUnitCode2, + timeToRespond: 50, + pbLg: '0.10', + pbMg: '0.10', + pbHg: '0.10', + pbAg: '0.10', + pbDg: '0.10', + pbCg: '', + size: '300x250', + adserverTargeting: { + hb_bidder: bidderCode, + hb_adid: '9999e27a5752fb', + hb_pb: '0.10' + }, + status: 'rendered' +}; let bidAdjustment = {}; for (var k in bidResponse) bidAdjustment[k] = bidResponse[k]; bidAdjustment.cpm = 0.8; @@ -245,7 +293,7 @@ describe('Sovrn Analytics Adapter', function () { assert.equal(requests[0].timeout, timeout); let bids = requests[0].bids; assert(bids); - assert.equal(bids.length, 1); + assert.equal(bids.length, 2); assert.equal(bids[0].bidId, bidId); assert.equal(bids[0].bidder, bidderCode); assert.equal(bids[0].transactionId, tId); @@ -340,6 +388,29 @@ describe('Sovrn Analytics Adapter', function () { status: 'rendered', isAuctionWinner: true }; + let SecondAdUnitExpectedBids = { + adUnitCode: 'div2', + bidId: 'bidid2', + bidder: 'sovrn', + bidderRequestId: '10340af0c7dc72', + transactionId: '99dca3ee-a80a-46d7-a4a0-cbcba463d97e', + width: 300, + height: 250, + statusMessage: 'Bid available', + adId: '9999e27a5752fb', + mediaType: 'banner', + source: 'client', + cpm: 0.12, + creativeId: 'cridprebidrtb', + dealId: null, + currency: 'USD', + netRevenue: true, + ttl: 60000, + timeToRespond: 50, + size: '300x250', + status: 'rendered', + isAuctionWinner: true + }; let expectedAdServerTargeting = { hb_bidder: 'sovrn', hb_adid: '3870e27a5752fb', @@ -363,6 +434,7 @@ describe('Sovrn Analytics Adapter', function () { emitEvent('AUCTION_INIT', auctionInit, auctionId); emitEvent('BID_REQUESTED', bidRequested, auctionId); emitEvent('BID_RESPONSE', bidResponse, auctionId); + emitEvent('BID_RESPONSE', bidResponse2, auctionId) emitEvent('AUCTION_END', {}, auctionId); let requestBody = JSON.parse(requests[0].requestBody); let requestsFromRequestBody = requestBody.requests[0]; @@ -371,6 +443,8 @@ describe('Sovrn Analytics Adapter', function () { expect(requestBody.timeouts).to.deep.equal({buffer: 400, bidder: 3000}); expect(requestsFromRequestBody).to.deep.include(expectedRequests); expect(bidsFromRequests).to.deep.include(expectedBids); + let bidsFromRequests2 = requestsFromRequestBody.bids[1]; + expect(bidsFromRequests2).to.deep.include(SecondAdUnitExpectedBids); expect(bidsFromRequests.adserverTargeting).to.deep.include(expectedAdServerTargeting); }); }); From 977b827ada7b6839397789b5fe239a2d76f984a7 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 9 Jul 2019 13:29:21 -0400 Subject: [PATCH 066/436] update sizeConfig logic around multiformat bids (#3938) --- src/sizeMapping.js | 4 +- test/spec/sizeMapping_spec.js | 105 ++++++++++++++++++++++++++++++---- 2 files changed, 95 insertions(+), 14 deletions(-) diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 04c9773a1af..cde3b4a4d15 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -88,9 +88,9 @@ export function resolveStatus({labels = [], labelAll = false, activeLabels = []} let results = { active: ( - allMediaTypes.length > 1 || (allMediaTypes.length === 1 && allMediaTypes[0] !== 'banner') + allMediaTypes.every(type => type !== 'banner') ) || ( - allMediaTypes[0] === 'banner' && deepAccess(mediaTypes, 'banner.sizes.length') > 0 && ( + allMediaTypes.some(type => type === 'banner') && deepAccess(mediaTypes, 'banner.sizes.length') > 0 && ( labels.length === 0 || ( (!labelAll && ( labels.some(label => maps.labels[label]) || diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index f85da4cba0b..254dcb8003e 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -66,13 +66,6 @@ describe('sizeMapping', function () { } return matchMediaOverride; }); - - sandbox.stub(window, 'matchMedia').callsFake((...args) => { - if (typeof matchMediaOverride === 'function') { - return matchMediaOverride.apply(window, args); - } - return matchMediaOverride; - }); }); afterEach(function () { @@ -161,15 +154,14 @@ describe('sizeMapping', function () { }); }); - it('should filter all banner sizes but not disable adUnit if multiple mediaTypes are present', function () { + it('should filter all banner sizes and should disable the adUnit even if other mediaTypes are present', function () { matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, Object.assign({}, testSizes, { native: { type: 'image' } }), undefined, sizeConfig); - expect(status.active).to.equal(true); + expect(status.active).to.equal(false); expect(status.mediaTypes).to.deep.equal({ banner: { sizes: [] @@ -210,12 +202,101 @@ describe('sizeMapping', function () { expect(status.mediaTypes).to.deep.equal(testSizes); }); + it('should activate/decactivate adUnits/bidders based on labels with multiformat ads', function () { + matchMediaOverride = (str) => str === '(min-width: 768px) and (max-width: 1199px)' ? {matches: true} : {matches: false}; + + let multiFormatSizes = { + banner: { + sizes: [[728, 90], [300, 300]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }; + + let status = resolveStatus({ + labels: ['tablet', 'test'], + labelAll: true + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[728, 90]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[728, 90]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + + multiFormatSizes.banner.sizes.splice(0, 1, [728, 80]); + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + + delete multiFormatSizes.banner; + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [300, 300] + } + }); + }); + it('should active/deactivate adUnits/bidders based on requestBids labels', function () { let activeLabels = ['us-visitor', 'desktop', 'smart']; let status = resolveStatus({ - labels: ['uk-visitor'], - activeLabels + labels: ['uk-visitor'], // from adunit + activeLabels // from requestBids.labels }, testSizes, undefined, sizeConfigWithLabels); expect(status.active).to.equal(false); From 3b0ad684562cfb77228388d2b9f2173e62432bb7 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 9 Jul 2019 12:45:31 -0600 Subject: [PATCH 067/436] add eslint plugin for checking imports (#3976) --- .eslintrc.js | 34 ++++++++++++++++- modules/ixBidAdapter.js | 3 +- package.json | 2 + plugins/eslint/package.json | 8 ++++ plugins/eslint/validateImports.js | 61 ++++++++++++++++++++++++++++++ src/adapters/analytics/example2.js | 2 +- 6 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 plugins/eslint/package.json create mode 100644 plugins/eslint/validateImports.js diff --git a/.eslintrc.js b/.eslintrc.js index 02ff81614c7..22b4f29d4e9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,13 @@ + +const sharedWhiteList = [ + "core-js/library/fn/array/find", // no ie11 + "core-js/library/fn/array/includes", // no ie11 + "core-js/library/fn/set", // ie11 supports Set but not Set#values + "core-js/library/fn/string/includes", // no ie11 + "core-js/library/fn/number/is-integer", // no ie11, + "core-js/library/fn/array/from" // no ie11 +]; + module.exports = { "env": { "browser": true, @@ -11,6 +21,9 @@ module.exports = { } }, "extends": "standard", + "plugins": [ + "prebid" + ], "globals": { "$$PREBID_GLOBAL$$": false }, @@ -31,5 +44,24 @@ module.exports = { "no-throw-literal": "off", "no-undef": "off", "no-useless-escape": "off", - } + }, + "overrides": [{ + "files": "modules/**/*.js", + "rules": { + "prebid/validate-imports": ["error", [ + ...sharedWhiteList, + "jsencrypt", + "crypto-js" + ]] + } + }, { + "files": "src/**/*.js", + "rules": { + "prebid/validate-imports": ["error", [ + ...sharedWhiteList, + "fun-hooks/no-eval", + "just-clone" + ]] + } + }] }; diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index c63b920dc93..8d76d862655 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,7 +1,6 @@ import * as utils from '../src/utils'; import { BANNER } from '../src/mediaTypes'; import { config } from '../src/config'; -import isArray from 'core-js/library/fn/array/is-array'; import isInteger from 'core-js/library/fn/number/is-integer'; import { registerBidder } from '../src/adapters/bidderFactory'; @@ -92,7 +91,7 @@ function parseBid(rawBid, currency) { * @return {boolean} True if this is a valid size format, and false otherwise. */ function isValidSize(size) { - return isArray(size) && size.length === 2 && isInteger(size[0]) && isInteger(size[1]); + return Array.isArray(size) && size.length === 2 && isInteger(size[0]) && isInteger(size[1]); } /** diff --git a/package.json b/package.json index 5e2806fe5f4..b386981d85d 100755 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "eslint-plugin-node": "^5.1.0", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", + "eslint-plugin-prebid": "file:./plugins/eslint", "execa": "^1.0.0", "faker": "^3.1.0", "fs.extra": "^1.3.2", @@ -79,6 +80,7 @@ "mocha": "^5.0.0", "opn": "^5.4.0", "querystringify": "0.0.3", + "resolve-from": "^5.0.0", "sinon": "^4.1.3", "through2": "^2.0.3", "url-parse": "^1.0.5", diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json new file mode 100644 index 00000000000..fa18ad83718 --- /dev/null +++ b/plugins/eslint/package.json @@ -0,0 +1,8 @@ +{ + "name": "eslint-plugin-prebid", + "version": "1.0.0", + "description": "validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points", + "main": "validateImports.js", + "author": "the prebid.js contributors", + "license": "Apache-2.0" +} diff --git a/plugins/eslint/validateImports.js b/plugins/eslint/validateImports.js new file mode 100644 index 00000000000..c655902f7d3 --- /dev/null +++ b/plugins/eslint/validateImports.js @@ -0,0 +1,61 @@ + +let path = require('path'); +let _ = require('lodash'); +let resolveFrom = require('resolve-from'); + +function flagErrors(context, node, importPath) { + let absFileDir = path.dirname(context.getFilename()); + let absImportPath = path.resolve(absFileDir, importPath); + + try { + resolveFrom(absFileDir, importPath); + } catch (e) { + return context.report(node, `import "${importPath}" cannot be resolved`); + } + + if ( + Array.isArray(_.get(context, ['options', 0])) && + importPath.match(/^\w+/) && + !context.options[0].some(name => importPath.startsWith(name)) + ) { + context.report(node, `import "${importPath}" not in import whitelist`); + } else { + let absModulePath = path.resolve(__dirname, '../../modules'); + + // don't allow import of any files directly within modules folder or index.js files within modules' sub-folders + if ( + path.dirname(absImportPath) === absModulePath || ( + absImportPath.startsWith(absModulePath) && + path.basename(absImportPath) === 'index.js' + ) + ) { + context.report(node, `import "${importPath}" cannot require module entry point`); + } + } +} + +module.exports = { + rules: { + 'validate-imports': { + meta: { + docs: { + description: 'validates module imports can be found without custom webpack resolvers, are in module whitelist, and not module entry points' + } + }, + create: function(context) { + return { + "CallExpression[callee.name='require']"(node) { + let importPath = _.get(node, ['arguments', 0, 'value']); + if (importPath) { + flagErrors(context, node, importPath); + } + }, + ImportDeclaration(node) { + let importPath = node.source.value.trim(); + flagErrors(context, node, importPath); + } + } + } + } + } +}; diff --git a/src/adapters/analytics/example2.js b/src/adapters/analytics/example2.js index 6888507010d..b04e8874e48 100644 --- a/src/adapters/analytics/example2.js +++ b/src/adapters/analytics/example2.js @@ -1,4 +1,4 @@ -import { ajax } from 'src/ajax'; +import { ajax } from '../../../src/ajax'; /** * example2.js - analytics adapter for Example2 Analytics Endpoint example From f0db7f2197fc795ded168a67e20a69ec1585b44d Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 9 Jul 2019 14:57:04 -0400 Subject: [PATCH 068/436] Fix #3939 - update firefox specific code in renderAd function (#3980) * update browser specific code in renderAd function * update TODO comment --- src/prebid.js | 11 ++++++++++- test/spec/unit/pbjs_api_spec.js | 2 -- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 1b6a40aff97..90f6365585e 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -325,7 +325,16 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`; emitAdRenderFail(PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid); } else if (ad) { - doc.open('text/html', 'replace'); + // will check if browser is firefox and below version 67, if so execute special doc.open() + // for details see: https://github.com/prebid/Prebid.js/pull/3524 + // TODO remove this browser specific code at later date (when Firefox < 67 usage is mostly gone) + if (navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('firefox/') > -1) { + const firefoxVerRegx = /firefox\/([\d\.]+)/; + let firefoxVer = navigator.userAgent.toLowerCase().match(firefoxVerRegx)[1]; // grabs the text in the 1st matching group + if (firefoxVer && parseInt(firefoxVer, 10) < 67) { + doc.open('text/html', 'replace'); + } + } doc.write(ad); doc.close(); setRenderSize(doc, width, height); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index b734faf9dd5..d4daec0c266 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -990,7 +990,6 @@ describe('Unit: Prebid Module', function () { beforeEach(function () { doc = { - open: sinon.spy(), write: sinon.spy(), close: sinon.spy(), defaultView: { @@ -1041,7 +1040,6 @@ describe('Unit: Prebid Module', function () { }); adResponse.ad = ""; $$PREBID_GLOBAL$$.renderAd(doc, bidId); - assert.ok(doc.open, 'open method called'); assert.ok(doc.write.calledWith(adResponse.ad), 'ad was written to doc'); assert.ok(doc.close.called, 'close method called'); }); From 4ec8711f93047aa0872abcb36b79e51b82e9ab24 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 9 Jul 2019 14:05:09 -0700 Subject: [PATCH 069/436] Prebid 2.23.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b386981d85d..06cd486c14c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.23.0-pre", + "version": "2.23.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From fe47224f4f0f32506b1eed49f9e62e880c315fb0 Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Tue, 9 Jul 2019 14:20:12 -0700 Subject: [PATCH 070/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06cd486c14c..5ca8c03783d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.23.0", + "version": "2.24.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8e2715acda45cfa983fbdb95c65a2f37a01b10c3 Mon Sep 17 00:00:00 2001 From: Andrew Muraco Date: Thu, 11 Jul 2019 14:58:28 -0400 Subject: [PATCH 071/436] Synacor media bidder updates: filter bad sizes & extra video parameters (#3885) * Synacor media bidder updates: - Filter out 1x1 & 1x2 adsizes that we don't support - Added a bunch of openrtb video params * SynacormediaBidAdapter: Replace let with const * SynacormediaBidAdapter: Replace let with const * SynacormediaBidAdapter: Updated setValidVideoParams Updated setValidVideoParams so that the length check works correctly. --- modules/synacormediaBidAdapter.js | 99 ++++++++------ modules/synacormediaBidAdapter.md | 16 +-- .../modules/synacormediaBidAdapter_spec.js | 129 ++++++++++++++++++ 3 files changed, 195 insertions(+), 49 deletions(-) diff --git a/modules/synacormediaBidAdapter.js b/modules/synacormediaBidAdapter.js index 3339ecfb04f..ca533f8cff8 100644 --- a/modules/synacormediaBidAdapter.js +++ b/modules/synacormediaBidAdapter.js @@ -7,8 +7,11 @@ import includes from 'core-js/library/fn/array/includes'; const BID_HOST = '//prebid.technoratimedia.com'; const USER_SYNC_HOST = '//ad-cdn.technoratimedia.com'; -const VIDEO_PARAMS = [ 'minduration', 'maxduration' ]; - +const VIDEO_PARAMS = [ 'minduration', 'maxduration', 'startdelay', 'placement', 'linearity', 'mimes', 'protocols', 'api' ]; +const BLOCKED_AD_SIZES = [ + '1x1', + '1x2' +]; export const spec = { code: 'synacormedia', supportedMediaTypes: [ BANNER, VIDEO ], @@ -19,15 +22,17 @@ export const spec = { bid.mediaTypes.hasOwnProperty('video'); }, isBidRequestValid: function(bid) { - return !!(bid && bid.params && bid.params.placementId && bid.params.seatId); + const hasRequiredParams = bid && bid.params && bid.params.hasOwnProperty('placementId') && bid.params.hasOwnProperty('seatId'); + const hasAdSizes = bid && getAdUnitSizes(bid).filter(size => BLOCKED_AD_SIZES.indexOf(size.join('x')) === -1).length > 0 + return !!(hasRequiredParams && hasAdSizes); }, buildRequests: function(validBidReqs, bidderRequest) { if (!validBidReqs || !validBidReqs.length || !bidderRequest) { return; } - let refererInfo = bidderRequest.refererInfo; - let openRtbBidRequest = { + const refererInfo = bidderRequest.refererInfo; + const openRtbBidRequest = { id: bidderRequest.auctionId, site: { domain: location.hostname, @@ -40,6 +45,7 @@ export const spec = { imp: [] }; let seatId = null; + validBidReqs.forEach((bid, i) => { if (seatId && seatId !== bid.params.seatId) { logWarn(`Synacormedia: there is an inconsistent seatId: ${bid.params.seatId} but only sending bid requests for ${seatId}, you should double check your configuration`); @@ -47,8 +53,8 @@ export const spec = { } else { seatId = bid.params.seatId; } - let placementId = bid.params.placementId; - let bidFloor = bid.params.bidfloor ? parseFloat(bid.params.bidfloor) : null; + const placementId = bid.params.placementId; + const bidFloor = bid.params.bidfloor ? parseFloat(bid.params.bidfloor) : null; if (isNaN(bidFloor)) { logWarn(`Synacormedia: there is an invalid bid floor: ${bid.params.bidfloor}`); } @@ -57,34 +63,39 @@ export const spec = { logWarn(`Synacormedia: there is an invalid POS: ${bid.params.pos}`); pos = 0; } - let videoOrBannerKey = this.isVideoBid(bid) ? 'video' : 'banner'; - getAdUnitSizes(bid).forEach((size, i) => { - if (!size || size.length != 2) { - return; - } - let size0 = size[0]; - let size1 = size[1]; - let imp = { - id: `${videoOrBannerKey.substring(0, 1)}${bid.bidId}-${size0}x${size1}`, - tagid: placementId - }; - if (bidFloor !== null && !isNaN(bidFloor)) { - imp.bidfloor = bidFloor; - } + const videoOrBannerKey = this.isVideoBid(bid) ? 'video' : 'banner'; + getAdUnitSizes(bid) + .filter(size => BLOCKED_AD_SIZES.indexOf(size.join('x')) === -1) + .forEach((size, i) => { + if (!size || size.length != 2) { + return; + } + const size0 = size[0]; + const size1 = size[1]; + const imp = { + id: `${videoOrBannerKey.substring(0, 1)}${bid.bidId}-${size0}x${size1}`, + tagid: placementId + }; + if (bidFloor !== null && !isNaN(bidFloor)) { + imp.bidfloor = bidFloor; + } - let videoOrBannerValue = { - w: size0, - h: size1, - pos - }; - if (videoOrBannerKey === 'video' && bid.params.video) { - Object.keys(bid.params.video) - .filter(param => includes(VIDEO_PARAMS, param) && !isNaN(parseInt(bid.params.video[param], 10))) - .forEach(param => videoOrBannerValue[param] = parseInt(bid.params.video[param], 10)); - } - imp[videoOrBannerKey] = videoOrBannerValue; - openRtbBidRequest.imp.push(imp); - }); + const videoOrBannerValue = { + w: size0, + h: size1, + pos + }; + if (videoOrBannerKey === 'video') { + if (bid.mediaTypes.video) { + this.setValidVideoParams(bid.mediaTypes.video, bid.params.video); + } + if (bid.params.video) { + this.setValidVideoParams(bid.params.video, videoOrBannerValue); + } + } + imp[videoOrBannerKey] = videoOrBannerValue; + openRtbBidRequest.imp.push(imp); + }); }); if (openRtbBidRequest.imp.length && seatId) { @@ -99,8 +110,14 @@ export const spec = { }; } }, + + setValidVideoParams: function (sourceObj, destObj) { + Object.keys(sourceObj) + .filter(param => includes(VIDEO_PARAMS, param) && sourceObj[param] !== null && (!isNaN(parseInt(sourceObj[param], 10)) || !(sourceObj[param].length < 1))) + .forEach(param => destObj[param] = Array.isArray(sourceObj[param]) ? sourceObj[param] : parseInt(sourceObj[param], 10)); + }, interpretResponse: function(serverResponse) { - var updateMacros = (bid, r) => { + const updateMacros = (bid, r) => { return r ? r.replace(/\${AUCTION_PRICE}/g, bid.price) : r; }; @@ -114,11 +131,11 @@ export const spec = { if (id && seatbids) { seatbids.forEach(seatbid => { seatbid.bid.forEach(bid => { - let creative = updateMacros(bid, bid.adm); - let nurl = updateMacros(bid, bid.nurl); - let [, impType, impid, width, height] = bid.impid.match(/^([vb])(.*)-(.*)x(.*)$/); - let isVideo = impType == 'v'; - let bidObj = { + const creative = updateMacros(bid, bid.adm); + const nurl = updateMacros(bid, bid.nurl); + const [, impType, impid, width, height] = bid.impid.match(/^([vb])(.*)-(.*)x(.*)$/); + const isVideo = impType == 'v'; + const bidObj = { requestId: impid, adId: bid.id.replace(/~/g, '-'), cpm: parseFloat(bid.price), @@ -132,7 +149,7 @@ export const spec = { ttl: 60 }; if (isVideo) { - let [, uuid] = nurl.match(/ID=([^&]*)&?/); + const [, uuid] = nurl.match(/ID=([^&]*)&?/); bidObj.videoCacheKey = encodeURIComponent(uuid); bidObj.vastUrl = nurl; } diff --git a/modules/synacormediaBidAdapter.md b/modules/synacormediaBidAdapter.md index 1f225aa0b2a..3a00aa45fed 100644 --- a/modules/synacormediaBidAdapter.md +++ b/modules/synacormediaBidAdapter.md @@ -38,26 +38,26 @@ https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_cache_id_synacorm }] },{ code: 'test-div2', - mediaType: { + mediaTypes: { video: { - context: 'instream', - playerSizes: [ - [300, 250] - ], + context: 'instream', + playerSize: [[300, 250]], } }, bids: [{ bidder: "synacormedia", params: { seatId: "prebid", - placementId: "demo1" + placementId: "demo1", bidfloor: 0.20, pos: 1, video: { minduration: 15, - maxduration: 30 + maxduration: 30, + startdelay: 1, + linearity: 1 } } }] - }]; + }]; ``` diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/synacormediaBidAdapter_spec.js index e86bf81a6a7..d2f024181a4 100644 --- a/test/spec/modules/synacormediaBidAdapter_spec.js +++ b/test/spec/modules/synacormediaBidAdapter_spec.js @@ -7,6 +7,7 @@ describe('synacormediaBidAdapter ', function () { let bid; beforeEach(function () { bid = { + sizes: [300, 250], params: { seatId: 'prebid', placementId: '1234' @@ -18,14 +19,26 @@ describe('synacormediaBidAdapter ', function () { assert(spec.isBidRequestValid(bid)); }); + it('should return false when sizes are missing', function () { + delete bid.sizes; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + + it('should return false when the only size is unwanted', function () { + bid.sizes = [[1, 1]]; + assert.isFalse(spec.isBidRequestValid(bid)); + }); + it('should return false when seatId param is missing', function () { delete bid.params.seatId; assert.isFalse(spec.isBidRequestValid(bid)); }); + it('should return false when placementId param is missing', function () { delete bid.params.placementId; assert.isFalse(spec.isBidRequestValid(bid)); }); + it('should return false when params is missing or null', function () { assert.isFalse(spec.isBidRequestValid({ params: null })); assert.isFalse(spec.isBidRequestValid({})); @@ -404,6 +417,122 @@ describe('synacormediaBidAdapter ', function () { req = spec.buildRequests([validBidReqInvalidSize], bidderRequest); assert.isUndefined(req); }); + it('should use all the video params in the impression request', function () { + let validBidRequestVideo = { + bidder: 'synacormedia', + params: { + seatId: 'prebid', + placementId: '1234', + video: { + minduration: 30, + maxduration: 45, + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'], + protocols: [1], + api: 1 + } + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[ 640, 480 ]] + } + }, + adUnitCode: 'video1', + transactionId: '93e5def8-29aa-4fe8-bd3a-0298c39f189a', + sizes: [[ 640, 480 ]], + bidId: '2624fabbb078e8', + bidderRequestId: '117954d20d7c9c', + auctionId: 'defd525f-4f1e-4416-a4cb-ae53be90e706', + src: 'client', + bidRequestsCount: 1 + }; + + let req = spec.buildRequests([validBidRequestVideo], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + video: { + h: 480, + pos: 0, + w: 640, + minduration: 30, + maxduration: 45, + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'], + protocols: [1], + api: 1 + }, + id: 'v2624fabbb078e8-640x480', + tagid: '1234', + } + ]); + }); + it('should move any video params in the mediaTypes object to params.video object', function () { + let validBidRequestVideo = { + bidder: 'synacormedia', + params: { + seatId: 'prebid', + placementId: '1234', + video: { + minduration: 30, + maxduration: 45, + protocols: [1], + api: 1 + } + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[ 640, 480 ]], + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'] + } + }, + adUnitCode: 'video1', + transactionId: '93e5def8-29aa-4fe8-bd3a-0298c39f189a', + sizes: [[ 640, 480 ]], + bidId: '2624fabbb078e8', + bidderRequestId: '117954d20d7c9c', + auctionId: 'defd525f-4f1e-4416-a4cb-ae53be90e706', + src: 'client', + bidRequestsCount: 1 + }; + + let req = spec.buildRequests([validBidRequestVideo], bidderRequest); + expect(req).to.have.property('method', 'POST'); + expect(req).to.have.property('url'); + expect(req.url).to.contain('//prebid.technoratimedia.com/openrtb/bids/prebid?src=$$REPO_AND_VERSION$$'); + expect(req.data.id).to.equal('xyz123'); + expect(req.data.imp).to.eql([ + { + video: { + h: 480, + pos: 0, + w: 640, + minduration: 30, + maxduration: 45, + startdelay: 1, + linearity: 1, + placement: 1, + mimes: ['video/mp4'], + protocols: [1], + api: 1 + }, + id: 'v2624fabbb078e8-640x480', + tagid: '1234', + } + ]); + }); }); describe('interpretResponse', function () { From a9933b4caae92d72919076287d3f942cde563d86 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 11 Jul 2019 12:03:04 -0700 Subject: [PATCH 072/436] Adding a method pbjs.getUserIds to share userIds in Prebid to external codes (#3889) * Adding a mthod pbjs.getUserIds to share userIds in Prebid to external codes - Need an API to share the UserIds retrieved by Prebid with external codes - Use casse: UserIds can be passed to Wrappers like A9/EB - Added pbjs.getUserIds method - Moved the cide that initalizes all sub-modules and calls passbacks into a separate function - Moved code to combine submodule ids in an object into a separate function * implemented code suggestion chnages * fixed eslint issue --- modules/userId/index.js | 60 +++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index e83258a4e02..16421e39e20 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -199,12 +199,12 @@ function processSubmoduleCallbacks(submodules) { } /** - * @param {AdUnit[]} adUnits + * This function will create a combined object for all subModule Ids * @param {SubmoduleContainer[]} submodules */ -function addIdDataToAdUnitBids(adUnits, submodules) { - if ([adUnits, submodules].some(i => !Array.isArray(i) || !i.length)) { - return; +function getCombinedSubmoduleIds(submodules) { + if (!Array.isArray(submodules) || !submodules.length) { + return {}; } const combinedSubmoduleIds = submodules.filter(i => utils.isPlainObject(i.idObj) && Object.keys(i.idObj).length).reduce((carry, i) => { Object.keys(i.idObj).forEach(key => { @@ -212,6 +212,19 @@ function addIdDataToAdUnitBids(adUnits, submodules) { }); return carry; }, {}); + + return combinedSubmoduleIds; +} + +/** + * @param {AdUnit[]} adUnits + * @param {SubmoduleContainer[]} submodules + */ +function addIdDataToAdUnitBids(adUnits, submodules) { + if ([adUnits].some(i => !Array.isArray(i) || !i.length)) { + return; + } + const combinedSubmoduleIds = getCombinedSubmoduleIds(submodules); if (Object.keys(combinedSubmoduleIds).length) { adUnits.forEach(adUnit => { adUnit.bids.forEach(bid => { @@ -223,15 +236,9 @@ function addIdDataToAdUnitBids(adUnits, submodules) { } /** - * Hook is executed before adapters, but after consentManagement. Consent data is requied because - * this module requires GDPR consent with Purpose #1 to save data locally. - * The two main actions handled by the hook are: - * 1. check gdpr consentData and handle submodule initialization. - * 2. append user id data (loaded from cookied/html or from the getId method) to bids to be accessed in adapters. - * @param {Object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids. - * @param {function} fn required; The next function in the chain, used by hook.js + * This is a common function that will initalize subModules if not already done and it will also execute subModule callbacks */ -export function requestBidsHook(fn, reqBidsConfigObj) { +function initializeSubmodulesAndExecuteCallbacks() { // initialize submodules only when undefined if (typeof initializedSubmodules === 'undefined') { initializedSubmodules = initSubmodules(submodules, gdprDataHandler.getConsentData()); @@ -256,14 +263,36 @@ export function requestBidsHook(fn, reqBidsConfigObj) { } } } +} +/** + * Hook is executed before adapters, but after consentManagement. Consent data is requied because + * this module requires GDPR consent with Purpose #1 to save data locally. + * The two main actions handled by the hook are: + * 1. check gdpr consentData and handle submodule initialization. + * 2. append user id data (loaded from cookied/html or from the getId method) to bids to be accessed in adapters. + * @param {Object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids. + * @param {function} fn required; The next function in the chain, used by hook.js + */ +export function requestBidsHook(fn, reqBidsConfigObj) { + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(); // pass available user id data to bid adapters addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, initializedSubmodules); - // calling fn allows prebid to continue processing return fn.call(this, reqBidsConfigObj); } +/** + * This function will be exposed in global-name-space so that userIds stored by Prebid UserId module can be used by external codes as well. + * Simple use case will be passing these UserIds to A9 wrapper solution + */ +function getUserIds() { + // initialize submodules only when undefined + initializeSubmodulesAndExecuteCallbacks(); + return getCombinedSubmoduleIds(initializedSubmodules); +}; + /** * @param {SubmoduleContainer[]} submodules * @param {ConsentData} consentData @@ -425,7 +454,10 @@ export function init(config) { syncDelay = utils.isNumber(userSync.syncDelay) ? userSync.syncDelay : DEFAULT_SYNC_DELAY; updateSubmodules(); } - }) + }); + + // exposing getUserIds function in global-name-space so that userIds stored in Prebid can be used by external codes. + (getGlobal()).getUserIds = getUserIds; } // init config update listener to start the application From 38b53f4038b44baea4cfaeadea21476f3e23d68e Mon Sep 17 00:00:00 2001 From: sumit116 Date: Fri, 12 Jul 2019 18:22:41 +0530 Subject: [PATCH 073/436] restrict outstream w/o renderer to PBS (#3881) * restrict outstream w/o renderer to PBS * reject Request to Prebid Server for invalid media types * add player height and width to response --- modules/prebidServerBidAdapter/index.js | 42 +++++++---- .../modules/prebidServerBidAdapter_spec.js | 75 +++++++++++++++++++ 2 files changed, 103 insertions(+), 14 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 4ac1bccaeda..e857bf1d665 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -495,11 +495,21 @@ const OPEN_RTB_PROTOCOL = { const imp = { id: adUnit.code, ext, secure: _s2sConfig.secure }; if (banner) { imp.banner = banner; } - if (video) { imp.video = video; } - - imps.push(imp); + if (video) { + if (video.context === 'outstream' && !adUnit.renderer) { + // Don't push oustream w/o renderer to request object. + utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); + } else { + imp.video = video; + } + } + if (imp.banner || imp.video) { imps.push(imp); } }); + if (!imps.length) { + utils.logError('Request to Prebid Server rejected due to invalid media type(s) in adUnit.') + return; + } const request = { id: s2sBidRequest.tid, source: {tid: s2sBidRequest.tid}, @@ -626,6 +636,9 @@ const OPEN_RTB_PROTOCOL = { if (utils.deepAccess(bid, 'ext.prebid.type') === VIDEO) { bidObject.mediaType = VIDEO; + let sizes = bidRequest.sizes && bidRequest.sizes[0]; + bidObject.playerHeight = sizes[0]; + bidObject.playerWidth = sizes[1]; // try to get cache values from 'response.ext.prebid.cache' // else try 'bid.ext.prebid.targeting' as fallback @@ -721,17 +734,18 @@ export function PrebidServer() { } const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, adUnitsWithSizes); - const requestJson = JSON.stringify(request); - - ajax( - _s2sConfig.endpoint, - { - success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), - error: done - }, - requestJson, - { contentType: 'text/plain', withCredentials: true } - ); + const requestJson = request && JSON.stringify(request); + if (request && requestJson) { + ajax( + _s2sConfig.endpoint, + { + success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done), + error: done + }, + requestJson, + { contentType: 'text/plain', withCredentials: true } + ); + } }; /* Notify Prebid of bid responses so bids can get in the auction */ diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index e2a3a5b111a..9562b2f4c07 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -80,6 +80,69 @@ const VIDEO_REQUEST = { ] }; +const OUTSTREAM_VIDEO_REQUEST = { + 'account_id': '1', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'max_bids': 1, + 'timeout_millis': 1000, + 'secure': 0, + 'url': '', + 'prebid_version': '1.4.0-pre', + 'ad_units': [ + { + 'code': 'div-gpt-ad-1460505748561-0', + 'sizes': [640, 480], + 'mediaTypes': { + 'video': { + playerSize: [[ 640, 480 ]], + context: 'outstream', + mimes: ['video/mp4'] + }, + banner: { sizes: [[300, 250]] } + }, + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'bids': [ + { + 'bid_id': '123', + 'bidder': 'appnexus', + 'params': { 'placementId': '12349520' } + } + ] + }, + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream', + mimes: ['video/mp4'] + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 13232385, + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + } + ], + renderer: { + url: 'http://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', + render: function (bid) { + ANOutstreamVideo.renderAd({ + targetId: bid.adUnitCode, + adResponse: bid.adResponse, + }); + } + } + } + ] +}; + let BID_REQUESTS; const RESPONSE = { @@ -390,6 +453,18 @@ describe('S2S Adapter', function () { xhr.restore(); }); + it('should not add outstrean without renderer', function() { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + + config.setConfig({s2sConfig: ortb2Config}); + adapter.callBids(OUTSTREAM_VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.imp[0].banner).to.exist; + expect(requestBid.imp[0].video).to.not.exist; + }); + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); From e5e36f7ebcf6ff5dce5f710d3214ce4f3f53fbfd Mon Sep 17 00:00:00 2001 From: bidphysics <48674658+bidphysics@users.noreply.github.com> Date: Fri, 12 Jul 2019 21:19:49 +0200 Subject: [PATCH 074/436] bidphysics adapter update aliases (#3985) --- modules/bidphysicsBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/bidphysicsBidAdapter.js b/modules/bidphysicsBidAdapter.js index 9f1dc83d427..cbd76c8bc10 100644 --- a/modules/bidphysicsBidAdapter.js +++ b/modules/bidphysicsBidAdapter.js @@ -10,7 +10,7 @@ const DEFAULT_NET_REVENUE = true; export const spec = { code: 'bidphysics', - aliases: ['yieldlift', 'padsquad'], + aliases: ['yieldlift'], supportedMediaTypes: [BANNER], isBidRequestValid: function (bid) { From 9ddf9152f1c725a49925cd29426bb150ec492914 Mon Sep 17 00:00:00 2001 From: ADman Media Date: Mon, 15 Jul 2019 14:53:37 +0200 Subject: [PATCH 075/436] Fix typo (#3986) * Add Adman bid adapter * Add supportedMediaTypes property * Update ADman Media bidder adapter * Remove console.log * Fix typo * revert package-json.lock * Delete package-lock.json * back to original package-lock.json --- modules/admanBidAdapter.js | 2 +- test/spec/modules/admanBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/admanBidAdapter.js b/modules/admanBidAdapter.js index 2fd8c2e96f0..4720d06d094 100644 --- a/modules/admanBidAdapter.js +++ b/modules/admanBidAdapter.js @@ -17,7 +17,7 @@ export const spec = { const ENDPOINT_URL = '//bidtor.admanmedia.com/prebid'; const bids = validBidRequests.map(buildRequestObject); const payload = { - referrer: utils.getTopWindowUrl(), + referer: utils.getTopWindowUrl(), bids, deviceWidth: screen.width }; diff --git a/test/spec/modules/admanBidAdapter_spec.js b/test/spec/modules/admanBidAdapter_spec.js index 2af040103cc..37a097427d5 100644 --- a/test/spec/modules/admanBidAdapter_spec.js +++ b/test/spec/modules/admanBidAdapter_spec.js @@ -86,7 +86,7 @@ describe('admanBidAdapter', function() { expect(payload.gdpr).to.exist; expect(payload.bids).to.exist.and.to.be.an('array').and.to.have.lengthOf(1); - expect(payload.referrer).to.exist; + expect(payload.referer).to.exist; const bid = payload.bids[0]; expect(bid).to.exist; From dd53ae1e35958affc50997286206bd2093e95f2d Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Mon, 15 Jul 2019 12:29:17 -0700 Subject: [PATCH 076/436] Fixing the issue introduced in #3845 for rubi analytics adapter (#3996) * Fixing the issue introduced in #3845 for rubi analytics adapter * using utils.deepClone instead of custom clone --- modules/rubiconAnalyticsAdapter.js | 10 ++-- .../modules/rubiconAnalyticsAdapter_spec.js | 35 +++++++++++- test/spec/modules/rubiconBidAdapter_spec.js | 56 +++++++++---------- 3 files changed, 65 insertions(+), 36 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index 6c4e1b88d8b..a00c727d470 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -232,17 +232,17 @@ function sendMessage(auctionId, bidWonId) { ); } -function parseBidResponse(bid) { +export function parseBidResponse(bid) { return _pick(bid, [ - 'getCpmInNewCurrency as bidPriceUSD', (fn) => { + 'bidPriceUSD', () => { if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { return Number(bid.cpm); } // use currency conversion function if present - if (typeof fn === 'function') { - return Number(fn('USD')); + if (typeof bid.getCpmInNewCurrency === 'function') { + return Number(bid.getCpmInNewCurrency('USD')); } - // TODO: throw error or something if not USD and currency module wasn't present? + utils.logWarn('Rubicon Analytics Adapter: Could not determine the bidPriceUSD of the bid ', bid); }, 'dealId', 'status', diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index efb7a1725e7..c6b0ca8d29f 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -1,7 +1,12 @@ -import rubiconAnalyticsAdapter, { SEND_TIMEOUT } from 'modules/rubiconAnalyticsAdapter'; +import rubiconAnalyticsAdapter, { SEND_TIMEOUT, parseBidResponse } from 'modules/rubiconAnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import { config } from 'src/config'; +import { + setConfig, + addBidResponseHook, +} from 'modules/currency'; + let Ajv = require('ajv'); let schema = require('./rubiconAnalyticsSchema.json'); let ajv = new Ajv({ @@ -694,5 +699,33 @@ describe('rubicon analytics adapter', function () { expect(timedOutBid.error.code).to.equal('timeout-error'); expect(timedOutBid).to.not.have.property('bidResponse'); }); + + it('should successfully convert bid price to USD in parseBidResponse', function () { + // Set the rates + setConfig({ + adServerCurrency: 'JPY', + rates: { + USD: { + JPY: 100 + } + } + }); + + // set our bid response to JPY + const bidCopy = utils.deepClone(BID2); + bidCopy.currency = 'JPY'; + bidCopy.cpm = 100; + + // Now add the bidResponse hook which hooks on the currenct conversion function onto the bid response + let innerBid; + addBidResponseHook(function(adCodeId, bid) { + innerBid = bid; + }, 'elementId', bidCopy); + + // Use the rubi analytics parseBidResponse Function to get the resulting cpm from the bid response! + const bidResponseObj = parseBidResponse(innerBid); + expect(bidResponseObj).to.have.property('bidPriceUSD'); + expect(bidResponseObj.bidPriceUSD).to.equal(1.0); + }); }); }); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 67a92d4a26e..0ad20001536 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -470,7 +470,7 @@ describe('the rubicon adapter', function () { }); it('should use rubicon sizes if present (including non-mappable sizes)', function () { - var sizesBidderRequest = clone(bidderRequest); + var sizesBidderRequest = utils.deepClone(bidderRequest); sizesBidderRequest.bids[0].params.sizes = [55, 57, 59, 801]; let [request] = spec.buildRequests(sizesBidderRequest.bids, sizesBidderRequest); @@ -481,7 +481,7 @@ describe('the rubicon adapter', function () { }); it('should not validate bid request if no valid sizes', function () { - var sizesBidderRequest = clone(bidderRequest); + var sizesBidderRequest = utils.deepClone(bidderRequest); sizesBidderRequest.bids[0].sizes = [[621, 250], [300, 251]]; let result = spec.isBidRequestValid(sizesBidderRequest.bids[0]); @@ -490,7 +490,7 @@ describe('the rubicon adapter', function () { }); it('should not validate bid request if no account id is present', function () { - var noAccountBidderRequest = clone(bidderRequest); + var noAccountBidderRequest = utils.deepClone(bidderRequest); delete noAccountBidderRequest.bids[0].params.accountId; let result = spec.isBidRequestValid(noAccountBidderRequest.bids[0]); @@ -499,7 +499,7 @@ describe('the rubicon adapter', function () { }); it('should allow a floor override', function () { - var floorBidderRequest = clone(bidderRequest); + var floorBidderRequest = utils.deepClone(bidderRequest); floorBidderRequest.bids[0].params.floor = 2; let [request] = spec.buildRequests(floorBidderRequest.bids, floorBidderRequest); @@ -876,17 +876,17 @@ describe('the rubicon adapter', function () { 'rf': 'localhost' }; - const bidCopy = clone(bidderRequest.bids[0]); + const bidCopy = utils.deepClone(bidderRequest.bids[0]); bidCopy.params.siteId = '70608'; bidCopy.params.zoneId = '1111'; bidderRequest.bids.push(bidCopy); - const bidCopy2 = clone(bidderRequest.bids[0]); + const bidCopy2 = utils.deepClone(bidderRequest.bids[0]); bidCopy2.params.siteId = '99999'; bidCopy2.params.zoneId = '2222'; bidderRequest.bids.push(bidCopy2); - const bidCopy3 = clone(bidderRequest.bids[0]); + const bidCopy3 = utils.deepClone(bidderRequest.bids[0]); bidCopy3.params.siteId = '99999'; bidCopy3.params.zoneId = '3333'; bidderRequest.bids.push(bidCopy3); @@ -970,7 +970,7 @@ describe('the rubicon adapter', function () { // TEST '10' BIDS, add 9 to 1 existing bid for (let i = 0; i < 9; i++) { - let bidCopy = clone(bidderRequest.bids[0]); + let bidCopy = utils.deepClone(bidderRequest.bids[0]); bidCopy.params.zoneId = `${i}0000`; bidderRequest.bids.push(bidCopy); } @@ -989,7 +989,7 @@ describe('the rubicon adapter', function () { // TEST '100' BIDS, add 90 to the previously added 10 for (let i = 0; i < 90; i++) { - let bidCopy = clone(bidderRequest.bids[0]); + let bidCopy = utils.deepClone(bidderRequest.bids[0]); bidCopy.params.zoneId = `${(i + 10)}0000`; bidderRequest.bids.push(bidCopy); } @@ -1013,14 +1013,14 @@ describe('the rubicon adapter', function () { return config[key]; }); - const bidCopy = clone(bidderRequest.bids[0]); + const bidCopy = utils.deepClone(bidderRequest.bids[0]); bidderRequest.bids.push(bidCopy); - const bidCopy2 = clone(bidderRequest.bids[0]); + const bidCopy2 = utils.deepClone(bidderRequest.bids[0]); bidCopy2.params.siteId = '32001'; bidderRequest.bids.push(bidCopy2); - const bidCopy3 = clone(bidderRequest.bids[0]); + const bidCopy3 = utils.deepClone(bidderRequest.bids[0]); bidCopy3.params.siteId = '32001'; bidderRequest.bids.push(bidCopy3); @@ -1036,18 +1036,18 @@ describe('the rubicon adapter', function () { return config[key]; }); - const bidCopy = clone(bidderRequest.bids[0]); + const bidCopy = utils.deepClone(bidderRequest.bids[0]); bidderRequest.bids.push(bidCopy); - const bidCopy2 = clone(bidderRequest.bids[0]); + const bidCopy2 = utils.deepClone(bidderRequest.bids[0]); bidCopy2.params.siteId = '32001'; bidderRequest.bids.push(bidCopy2); - const bidCopy3 = clone(bidderRequest.bids[0]); + const bidCopy3 = utils.deepClone(bidderRequest.bids[0]); bidCopy3.params.siteId = '32001'; bidderRequest.bids.push(bidCopy3); - const bidCopy4 = clone(bidderRequest.bids[0]); + const bidCopy4 = utils.deepClone(bidderRequest.bids[0]); bidCopy4.mediaTypes = { video: { context: 'instream', @@ -1080,7 +1080,7 @@ describe('the rubicon adapter', function () { describe('user id config', function() { it('should send tpid_tdid when userId defines tdid', function () { - const clonedBid = clone(bidderRequest.bids[0]); + const clonedBid = utils.deepClone(bidderRequest.bids[0]); clonedBid.userId = { tdid: 'abcd-efgh-ijkl-mnop-1234' }; @@ -1137,7 +1137,7 @@ describe('the rubicon adapter', function () { it('should send request with proper ad position', function () { createVideoBidderRequest(); - let positionBidderRequest = clone(bidderRequest); + let positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].mediaTypes.video.pos = 1; let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(1); @@ -1173,25 +1173,25 @@ describe('the rubicon adapter', function () { it('should send request with proper ad position when mediaTypes.video.pos is not defined', function () { createVideoBidderRequest(); - let positionBidderRequest = clone(bidderRequest); + let positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = undefined; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; let [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(0); - positionBidderRequest = clone(bidderRequest); + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'atf' positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(1); - positionBidderRequest = clone(bidderRequest); + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'btf'; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); expect(request.data.imp[0].video.pos).to.equal(3); - positionBidderRequest = clone(bidderRequest); + positionBidderRequest = utils.deepClone(bidderRequest); positionBidderRequest.bids[0].params.position = 'foobar'; positionBidderRequest.bids[0].mediaTypes.video.pos = undefined; [request] = spec.buildRequests(positionBidderRequest.bids, positionBidderRequest); @@ -1216,7 +1216,7 @@ describe('the rubicon adapter', function () { bidderRequest.auctionStart + 100 ); - const bidRequestCopy = clone(bidderRequest.bids[0]); + const bidRequestCopy = utils.deepClone(bidderRequest.bids[0]); expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(true); // change context to outstream, still true @@ -1302,7 +1302,7 @@ describe('the rubicon adapter', function () { bidderRequest.auctionStart + 100 ); - const bidRequestCopy = clone(bidderRequest); + const bidRequestCopy = utils.deepClone(bidderRequest); let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(true); @@ -1350,7 +1350,7 @@ describe('the rubicon adapter', function () { bidderRequest.auctionStart + 100 ); - const bidRequestCopy = clone(bidderRequest); + const bidRequestCopy = utils.deepClone(bidderRequest); let requests = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); expect(requests.length).to.equal(1); @@ -1801,7 +1801,7 @@ describe('the rubicon adapter', function () { }; let bids = spec.interpretResponse({ body: response }, { - bidRequest: [clone(bidderRequest.bids[0])] + bidRequest: [utils.deepClone(bidderRequest.bids[0])] }); expect(bids).to.be.lengthOf(1); @@ -2135,7 +2135,3 @@ describe('the rubicon adapter', function () { }); }); }); - -function clone(obj) { - return JSON.parse(JSON.stringify(obj)); -} From a09046046e1435f742ad9763791acba4542da62c Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 16 Jul 2019 18:05:27 +0530 Subject: [PATCH 077/436] update karma and webpack-stream packages (#3966) --- package-lock.json | 1569 +++++++++++++++++++++------------------------ package.json | 4 +- 2 files changed, 742 insertions(+), 831 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d224cebc76..d0bfdfee34e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.21.0-pre", + "version": "2.23.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -856,6 +856,194 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -955,6 +1143,12 @@ "json-schema-traverse": "^0.3.0" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", @@ -987,7 +1181,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "dev": true, + "optional": true }, "ansi-colors": { "version": "3.2.3", @@ -1076,6 +1271,12 @@ "default-require-extensions": "^1.0.0" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -3108,6 +3309,54 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, + "cacache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", + "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3345,6 +3594,21 @@ "upath": "^1.1.1" } }, + "chownr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3531,15 +3795,6 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3741,6 +3996,31 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -3950,6 +4230,12 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3970,9 +4256,9 @@ } }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", + "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", "dev": true }, "date-now": { @@ -5597,40 +5883,6 @@ } } }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - } - } - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5681,30 +5933,6 @@ } } }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - }, - "dependencies": { - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -5998,6 +6226,12 @@ "detect-libc": "^1.0.3" } }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -6017,12 +6251,6 @@ "object-assign": "^4.0.1" } }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6186,9 +6414,9 @@ } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "flush-write-stream": { @@ -6356,6 +6584,18 @@ "through2": "^2.0.3" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", @@ -6401,7 +6641,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6422,12 +6663,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6442,17 +6685,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6569,7 +6815,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6581,6 +6828,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6595,6 +6843,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6602,12 +6851,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6626,6 +6877,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6706,7 +6958,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6718,6 +6971,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6803,7 +7057,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6839,6 +7094,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6858,6 +7114,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6901,12 +7158,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7032,42 +7291,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -8492,6 +8715,12 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8759,21 +8988,6 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -8869,18 +9083,6 @@ "isobject": "^3.0.1" } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -9397,28 +9599,27 @@ "dev": true }, "karma": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", + "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", + "braces": "^2.3.2", "chokidar": "^2.0.3", "colors": "^1.1.0", - "combine-lists": "^1.0.0", "connect": "^3.6.0", "core-js": "^2.2.0", "di": "^0.0.1", "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", + "lodash": "^4.17.11", + "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -10028,33 +10229,16 @@ } }, "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.4.0.tgz", + "integrity": "sha512-xwRvmxFsq8Hb7YeS+XKfvCrsH114bXex6mIwJ2+KmYVi23pB3+hlzyGq1JPycSFTJWNLhD/7PCtM0RfPy6/2yg==", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.5" } }, "loglevelnext": { @@ -10163,6 +10347,12 @@ "kind-of": "^6.0.2" } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10246,12 +10436,6 @@ } } }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -10633,6 +10817,24 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -10811,6 +11013,31 @@ } } }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11256,27 +11483,6 @@ "make-iterator": "^1.0.0" } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -11485,6 +11691,17 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -11677,35 +11894,6 @@ "ini": "^1.3.3" } }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -11905,12 +12093,6 @@ "sha.js": "^2.4.8" } }, - "pbkdf2-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", - "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", - "dev": true - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -12000,12 +12182,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12036,6 +12212,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12184,25 +12366,6 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12386,15 +12549,6 @@ "private": "^0.1.6" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -12825,6 +12979,15 @@ "is-promise": "^2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -12947,6 +13110,12 @@ } } }, + "serialize-javascript": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13573,6 +13742,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -13685,6 +13863,16 @@ "readable-stream": "^2.0.2" } }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -13711,17 +13899,27 @@ "dev": true }, "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", + "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11" }, "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13730,6 +13928,26 @@ "requires": { "ms": "^2.1.1" } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } } } }, @@ -13941,6 +14159,102 @@ "through2": "^2.0.1" } }, + "terser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.2.tgz", + "integrity": "sha512-IWLuJqTvx97KP3uTYkFVn93cXO+EtlzJu8TdJylq+H0VBDlPMIfQA9MBS5Vc5t3xTEUG1q0hIfHMpAP2R+gWTw==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "dev": true, + "requires": { + "cacache": "^11.3.2", + "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", + "loader-utils": "^1.2.3", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.0.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14195,6 +14509,12 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14275,7 +14595,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true + "dev": true, + "optional": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", @@ -14458,6 +14779,24 @@ } } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -14528,6 +14867,12 @@ "unist-util-is": "^3.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -15437,46 +15782,19 @@ } } }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "webpack-dev-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, - "dependencies": { - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", - "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" }, "dependencies": { "mime": { @@ -15518,548 +15836,132 @@ } }, "webpack-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", - "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", + "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", "dev": true, "requires": { - "gulp-util": "^3.0.7", + "fancy-log": "^1.3.3", "lodash.clone": "^4.3.2", "lodash.some": "^4.2.2", - "memory-fs": "^0.3.0", + "memory-fs": "^0.4.1", + "plugin-error": "^1.0.1", + "supports-color": "^5.5.0", "through": "^2.3.8", - "vinyl": "^1.1.0", - "webpack": "^1.12.9" + "vinyl": "^2.1.0", + "webpack": "^4.26.1" }, "dependencies": { "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", + "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", "dev": true }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "browserify-aes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", - "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true, - "requires": { - "inherits": "^2.0.1" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "~0.2.0" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, - "crypto-browserify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", - "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "dev": true, - "requires": { - "browserify-aes": "0.4.0", - "pbkdf2-compat": "2.0.1", - "ripemd160": "0.2.0", - "sha.js": "2.2.6" - } - }, "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, - "dependencies": { - "memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", - "dev": true - } - } - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", - "dev": true - }, - "interpret": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", - "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { + "fast-deep-equal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - }, - "memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "node-libs-browser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", - "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.1.4", - "buffer": "^4.9.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "0.0.1", - "os-browserify": "^0.2.0", - "path-browserify": "0.0.0", - "process": "^0.11.0", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.0.5", - "stream-browserify": "^2.0.1", - "stream-http": "^2.3.1", - "string_decoder": "^0.10.25", - "timers-browserify": "^2.0.2", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", - "dev": true - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "ripemd160": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", - "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", - "dev": true - }, - "sha.js": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", - "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "dev": true, - "requires": { - "async": "^0.9.0", - "chokidar": "^1.0.0", - "graceful-fs": "^4.1.2" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - } - } - }, "webpack": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", - "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true, - "requires": { - "acorn": "^3.0.0", - "async": "^1.3.0", - "clone": "^1.0.2", - "enhanced-resolve": "~0.9.0", - "interpret": "^0.6.4", - "loader-utils": "^0.2.11", - "memory-fs": "~0.3.0", + "version": "4.35.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.35.2.tgz", + "integrity": "sha512-TZAmorNymV4q66gAM/h90cEjG+N3627Q2MnkSgKlX/z3DlNVKUtqy57lz1WmZU2+FUZwzM+qm7cGaO95PyrX5A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", "mkdirp": "~0.5.0", - "node-libs-browser": "^0.7.0", - "optimist": "~0.6.0", - "supports-color": "^3.1.0", - "tapable": "~0.1.8", - "uglify-js": "~2.7.3", - "watchpack": "^0.2.1", - "webpack-core": "~0.6.9" - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^1.0.0", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" } } } @@ -16123,6 +16025,15 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index 5ca8c03783d..deafd23c1b7 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^3.1.3", + "karma": "^4.1.0", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^3.2.0", + "webpack-stream": "^5.2.1", "yargs": "^1.3.1" }, "dependencies": { From afa825bddaa5ecd8896161ceb94d78d75b848265 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 16 Jul 2019 13:46:37 -0400 Subject: [PATCH 078/436] Revert "update karma and webpack-stream packages (#3966)" (#4003) This reverts commit 6399ab1ab1c7215149389ac2a36ef4be6dce8826. --- package-lock.json | 1567 ++++++++++++++++++++++++--------------------- package.json | 4 +- 2 files changed, 830 insertions(+), 741 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0bfdfee34e..1d224cebc76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.23.0-pre", + "version": "2.21.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -856,194 +856,6 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1143,12 +955,6 @@ "json-schema-traverse": "^0.3.0" } }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", @@ -1181,8 +987,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true + "dev": true }, "ansi-colors": { "version": "3.2.3", @@ -1271,12 +1076,6 @@ "default-require-extensions": "^1.0.0" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -3309,54 +3108,6 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3594,21 +3345,6 @@ "upath": "^1.1.1" } }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3795,6 +3531,15 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "^4.5.0" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3996,31 +3741,6 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4230,12 +3950,6 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -4256,9 +3970,9 @@ } }, "date-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", - "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "date-now": { @@ -5883,6 +5597,40 @@ } } }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } + } + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5933,6 +5681,30 @@ } } }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + }, + "dependencies": { + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -6226,12 +5998,6 @@ "detect-libc": "^1.0.3" } }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -6251,6 +6017,12 @@ "object-assign": "^4.0.1" } }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6414,9 +6186,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { @@ -6584,18 +6356,6 @@ "through2": "^2.0.3" } }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", @@ -6641,8 +6401,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6663,14 +6422,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6685,20 +6442,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6815,8 +6569,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6828,7 +6581,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6843,7 +6595,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6851,14 +6602,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6877,7 +6626,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6958,8 +6706,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6971,7 +6718,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7057,8 +6803,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7094,7 +6839,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7114,7 +6858,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7158,14 +6901,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -7291,6 +7032,42 @@ "path-is-absolute": "^1.0.0" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -8715,12 +8492,6 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8988,6 +8759,21 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -9083,9 +8869,21 @@ "isobject": "^3.0.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, @@ -9599,27 +9397,28 @@ "dev": true }, "karma": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", - "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "braces": "^2.3.2", "chokidar": "^2.0.3", "colors": "^1.1.0", + "combine-lists": "^1.0.0", "connect": "^3.6.0", "core-js": "^2.2.0", "di": "^0.0.1", "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.11", - "log4js": "^4.0.0", + "lodash": "^4.17.5", + "log4js": "^3.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -10229,16 +10028,33 @@ } }, "log4js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.4.0.tgz", - "integrity": "sha512-xwRvmxFsq8Hb7YeS+XKfvCrsH114bXex6mIwJ2+KmYVi23pB3+hlzyGq1JPycSFTJWNLhD/7PCtM0RfPy6/2yg==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { - "date-format": "^2.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.0", - "rfdc": "^1.1.4", - "streamroller": "^1.0.5" + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" + }, + "dependencies": { + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, "loglevelnext": { @@ -10347,12 +10163,6 @@ "kind-of": "^6.0.2" } }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10436,6 +10246,12 @@ } } }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -10817,24 +10633,6 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -11013,31 +10811,6 @@ } } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11483,6 +11256,27 @@ "make-iterator": "^1.0.0" } }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -11691,17 +11485,6 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -11894,6 +11677,35 @@ "ini": "^1.3.3" } }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -12093,6 +11905,12 @@ "sha.js": "^2.4.8" } }, + "pbkdf2-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -12182,6 +12000,12 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12212,12 +12036,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12366,6 +12184,25 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12549,6 +12386,15 @@ "private": "^0.1.6" } }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -12979,15 +12825,6 @@ "is-promise": "^2.1.0" } }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -13110,12 +12947,6 @@ } } }, - "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", - "dev": true - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13742,15 +13573,6 @@ "tweetnacl": "~0.14.0" } }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -13863,16 +13685,6 @@ "readable-stream": "^2.0.2" } }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -13899,27 +13711,17 @@ "dev": true }, "streamroller": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", - "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11" + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" }, "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13928,26 +13730,6 @@ "requires": { "ms": "^2.1.1" } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } } } }, @@ -14159,102 +13941,6 @@ "through2": "^2.0.1" } }, - "terser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.2.tgz", - "integrity": "sha512-IWLuJqTvx97KP3uTYkFVn93cXO+EtlzJu8TdJylq+H0VBDlPMIfQA9MBS5Vc5t3xTEUG1q0hIfHMpAP2R+gWTw==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", - "dev": true, - "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", - "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14509,12 +14195,6 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14595,8 +14275,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true + "dev": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", @@ -14779,24 +14458,6 @@ } } }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -14867,12 +14528,6 @@ "unist-util-is": "^3.0.0" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -15782,15 +15437,42 @@ } } }, - "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", + "webpack-core": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" + }, + "dependencies": { + "source-list-map": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "webpack-dev-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", + "dev": true, + "requires": { + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", "path-is-absolute": "^1.0.0", "range-parser": "^1.0.3", "url-join": "^2.0.2", @@ -15836,132 +15518,548 @@ } }, "webpack-stream": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", - "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, "requires": { - "fancy-log": "^1.3.3", + "gulp-util": "^3.0.7", "lodash.clone": "^4.3.2", "lodash.some": "^4.2.2", - "memory-fs": "^0.4.1", - "plugin-error": "^1.0.1", - "supports-color": "^5.5.0", + "memory-fs": "^0.3.0", "through": "^2.3.8", - "vinyl": "^2.1.0", - "webpack": "^4.26.1" + "vinyl": "^1.1.0", + "webpack": "^1.12.9" }, "dependencies": { "acorn": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", - "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, - "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "dev": true, + "requires": { + "inherits": "^2.0.1" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "crypto-browserify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } + }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "memory-fs": "^0.2.0", + "tapable": "^0.1.8" + }, + "dependencies": { + "memory-fs": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", + "dev": true + } } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "is-posix-bracket": "^0.1.0" } }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", "dev": true }, - "schema-utils": { + "interpret": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", + "dev": true + }, + "is-extglob": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + }, + "memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "node-libs-browser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.0", + "path-browserify": "0.0.0", + "process": "^0.11.0", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.0.5", + "stream-browserify": "^2.0.1", + "stream-http": "^2.3.1", + "string_decoder": "^0.10.25", + "timers-browserify": "^2.0.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "remove-trailing-separator": "^1.0.1" + } + }, + "os-browserify": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "ripemd160": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", + "dev": true + }, + "sha.js": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", + "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" } }, "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, + "uglify-js": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "dev": true, + "requires": { + "async": "^0.9.0", + "chokidar": "^1.0.0", + "graceful-fs": "^4.1.2" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, "webpack": { - "version": "4.35.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.35.2.tgz", - "integrity": "sha512-TZAmorNymV4q66gAM/h90cEjG+N3627Q2MnkSgKlX/z3DlNVKUtqy57lz1WmZU2+FUZwzM+qm7cGaO95PyrX5A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.0.5", - "acorn-dynamic-import": "^4.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", + "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", + "dev": true, + "requires": { + "acorn": "^3.0.0", + "async": "^1.3.0", + "clone": "^1.0.2", + "enhanced-resolve": "~0.9.0", + "interpret": "^0.6.4", + "loader-utils": "^0.2.11", + "memory-fs": "~0.3.0", "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "node-libs-browser": "^0.7.0", + "optimist": "~0.6.0", + "supports-color": "^3.1.0", + "tapable": "~0.1.8", + "uglify-js": "~2.7.3", + "watchpack": "^0.2.1", + "webpack-core": "~0.6.9" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" } } } @@ -16025,15 +16123,6 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index deafd23c1b7..5ca8c03783d 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^4.1.0", + "karma": "^3.1.3", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^5.2.1", + "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, "dependencies": { From ba9fca7ce48603faff88b7dfce5a648cb5f07111 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:03:51 -0400 Subject: [PATCH 079/436] resize correct div (#3988) --- src/secureCreatives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 8505923c493..f8ba9477b52 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -81,7 +81,7 @@ export function _sendAdToCreative(adObject, remoteDomain, source) { function resizeRemoteCreative({ adUnitCode, width, height }) { // resize both container div + iframe - ['div', 'iframe'].forEach(elmType => { + ['div:last-child', 'div:last-child iframe'].forEach(elmType => { let element = getElementByAdUnit(elmType); if (element) { let elementStyle = element.style; From 502795c853c9fef4ecfe3509e0ab1f550d3023ad Mon Sep 17 00:00:00 2001 From: Ryan McNierney <45180751+rmcnierney@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:07:53 -0400 Subject: [PATCH 080/436] Triplelift adapter tdid support (#3983) * Add user support in _buildPostBody * Add tdid check to test spec * Remove comments * Removing package-lock.json changes --- modules/tripleliftBidAdapter.js | 28 +++++++++++++++++-- .../spec/modules/tripleliftBidAdapter_spec.js | 10 +++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 748c5087201..ab6180cf45d 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -17,7 +17,7 @@ export const tripleliftAdapterSpec = { buildRequests: function(bidRequests, bidderRequest) { let tlCall = STR_ENDPOINT; - let data = _buildPostBody(bidRequests); + let data = _buildPostBody(bidRequests, bidderRequest); tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); @@ -78,7 +78,7 @@ export const tripleliftAdapterSpec = { } } -function _buildPostBody(bidRequests) { +function _buildPostBody(bidRequests, bidderRequest) { let data = {}; data.imp = bidRequests.map(function(bid, index) { return { @@ -91,6 +91,13 @@ function _buildPostBody(bidRequests) { } }); + let eids = handleConsortiaUserIds(bidderRequest) + if (eids.length > 0) { + data.user = { + ext: {eids} + } + } + return data; } @@ -108,6 +115,23 @@ function _isValidSize(size) { return (size.length === 2 && typeof size[0] === 'number' && typeof size[1] === 'number'); } +function handleConsortiaUserIds(bidderRequest) { + let eids = []; + if (bidderRequest.userId && bidderRequest.userId.tdid) { + eids.push({ + source: 'adserver.org', + uids: [{ + id: bidderRequest.userId.tdid, + ext: { + rtiPartner: 'TDID' + } + }] + }) + } + + return eids; +} + function _buildResponseObject(bidderRequest, bid) { let bidResponse = {}; let width = bid.width || 1; diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 171a97bafd9..dbae392f941 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -89,6 +89,9 @@ describe('triplelift adapter', function () { gdprConsent: { consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', gdprApplies: true + }, + userId: { + tdid: '6bca7f6b-a98a-46c0-be05-6020f7604598' } }; @@ -112,6 +115,13 @@ describe('triplelift adapter', function () { expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); }); + it('should add tdid to the payload if included', function () { + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + const payload = request.data; + expect(payload).to.exist; + expect(payload.user).to.deep.equal({ext: {eids: [{source: 'adserver.org', uids: [{id: '6bca7f6b-a98a-46c0-be05-6020f7604598', ext: {rtiPartner: 'TDID'}}]}]}}); + }); + it('should return a query string for TL call', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const url = request.url; From 625a1eb657a90c996764253f22344c6437f4e347 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Tue, 16 Jul 2019 14:17:28 -0400 Subject: [PATCH 081/436] adding tdid support (#3981) --- modules/kargoBidAdapter.js | 18 +++++++--- test/spec/modules/kargoBidAdapter_spec.js | 42 +++++++++++++++-------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 5c3d59bd241..63406bf3ce4 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -22,6 +22,10 @@ export const spec = { bidIds[bid.bidId] = bid.params.placementId; bidSizes[bid.bidId] = bid.sizes; }); + let tdid; + if (validBidRequests.length > 0 && validBidRequests[0].userId && validBidRequests[0].userId.tdid) { + tdid = validBidRequests[0].userId.tdid; + } const transformedParams = Object.assign({}, { sessionId: spec._getSessionId(), timeout: bidderRequest.timeout, @@ -35,7 +39,7 @@ export const spec = { bidIDs: bidIds, bidSizes: bidSizes, prebidRawBidRequests: validBidRequests - }, spec._getAllMetadata()); + }, spec._getAllMetadata(tdid)); const encodedParams = encodeURIComponent(JSON.stringify(transformedParams)); return Object.assign({}, bidderRequest, { method: 'GET', @@ -159,14 +163,18 @@ export const spec = { } }, - _getUserIds() { + _getUserIds(tdid) { const crb = spec._getCrb(); - return { + const userIds = { kargoID: crb.userId, clientID: crb.clientId, crbIDs: crb.syncIds || {}, optOut: crb.optOut }; + if (tdid) { + userIds.tdID = tdid; + } + return userIds; }, _getClientId() { @@ -174,9 +182,9 @@ export const spec = { return crb.clientId; }, - _getAllMetadata() { + _getAllMetadata(tdid) { return { - userIDs: spec._getUserIds(), + userIDs: spec._getUserIds(tdid), krux: spec._getKrux(), pageURL: window.location.href, rawCRB: spec._readCookie('krg_crb'), diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index a6779f518a0..92f68fd9b91 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -58,6 +58,9 @@ describe('kargo adapter tests', function () { placementId: 'foo' }, bidId: 1, + userId: { + tdid: 'fake-tdid' + }, sizes: [[320, 50], [300, 250], [300, 600]] }, { @@ -239,6 +242,7 @@ describe('kargo adapter tests', function () { userIDs: { kargoID: '5f108831-302d-11e7-bf6b-4595acd3bf6c', clientID: '2410d8f2-c111-4811-88a5-7b5e190e475f', + tdID: 'fake-tdid', crbIDs: { 2: '82fa2555-5969-4614-b4ce-4dcf1080e9f9', 16: 'VoxIk8AoJz0AAEdCeyAAAAC2&502', @@ -267,6 +271,9 @@ describe('kargo adapter tests', function () { params: { placementId: 'foo' }, + userId: { + tdid: 'fake-tdid' + }, sizes: [[320, 50], [300, 250], [300, 600]] }, { @@ -292,6 +299,7 @@ describe('kargo adapter tests', function () { base.userIDs = { crbIDs: {} }; + delete base.prebidRawBidRequests[0].userId.tdid; } if (excludeKrux) { @@ -304,8 +312,12 @@ describe('kargo adapter tests', function () { return base; } - function testBuildRequests(expected) { - var request = spec.buildRequests(bids, {timeout: 200, foo: 'bar'}); + function testBuildRequests(excludeTdid, expected) { + var clonedBids = JSON.parse(JSON.stringify(bids)); + if (excludeTdid) { + delete clonedBids[0].userId.tdid; + } + var request = spec.buildRequests(clonedBids, {timeout: 200, foo: 'bar'}); expected.sessionId = getSessionId(); sessionIds.push(expected.sessionId); var krakenParams = JSON.parse(decodeURIComponent(request.data.slice(5))); @@ -330,23 +342,23 @@ describe('kargo adapter tests', function () { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); it('works when all params and cookies are correctly set but no localstorage', function() { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(true); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, null, getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, null, getKrgCrbOldStyle())); }); it('gracefully handles nothing being set', function() { - testBuildRequests(getExpectedKrakenParams(true, true, null, null)); + testBuildRequests(true, getExpectedKrakenParams(true, true, null, null)); }); it('gracefully handles browsers without localStorage', function() { simulateNoLocalStorage(); - testBuildRequests(getExpectedKrakenParams(true, true, null, null)); + testBuildRequests(true, getExpectedKrakenParams(true, true, null, null)); }); it('handles empty yet valid Kargo CRB', function() { @@ -354,49 +366,49 @@ describe('kargo adapter tests', function () { initializeKruxSegments(); initializeEmptyKrgCrb(); initializeEmptyKrgCrbCookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getEmptyKrgCrb(), getEmptyKrgCrbOldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, getEmptyKrgCrb(), getEmptyKrgCrbOldStyle())); }); it('handles broken Kargo CRBs where base64 encoding is invalid', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType1(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType1(), null)); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType1(), null)); }); it('handles broken Kargo CRBs where top level JSON is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType1Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType1())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType1())); }); it('handles broken Kargo CRBs where decoded JSON is invalid', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType2(); - testBuildRequests(getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType2(), null)); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, getInvalidKrgCrbType2(), null)); }); it('handles broken Kargo CRBs where inner base 64 is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType2Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType2OldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType2OldStyle())); }); it('handles broken Kargo CRBs where inner JSON is invalid on cookie', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType3Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType3OldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType3OldStyle())); }); it('handles broken Kargo CRBs where inner JSON is falsey', function() { initializeKruxUser(); initializeKruxSegments(); initializeInvalidKrgCrbType4Cookie(); - testBuildRequests(getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType4OldStyle())); + testBuildRequests(true, getExpectedKrakenParams(true, undefined, null, getInvalidKrgCrbType4OldStyle())); }); it('handles a non-existant currency object on the config', function() { @@ -404,7 +416,7 @@ describe('kargo adapter tests', function () { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); it('handles no ad server currency being set on the currency object in the config', function() { @@ -412,7 +424,7 @@ describe('kargo adapter tests', function () { initializeKruxUser(); initializeKruxSegments(); initializeKrgCrb(); - testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); + testBuildRequests(false, getExpectedKrakenParams(undefined, undefined, getKrgCrb(), getKrgCrbOldStyle())); }); }); From 120af4ac583c85c88cc5e187d7daf28d66f91289 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:20:48 -0400 Subject: [PATCH 082/436] update PR_REVIEW with some docs notes (#3994) * update PR_REVIEW with some docs notes * adding note about COPPA change --- PR_REVIEW.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PR_REVIEW.md b/PR_REVIEW.md index d5799472377..4ad8b8ec372 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -14,6 +14,11 @@ For modules and core platform updates, the initial reviewer should request an ad - Review for obvious errors or bad coding practice / use best judgement here. - If the change is a new feature / change to core prebid.js - review the change with a Tech Lead on the project and make sure they agree with the nature of change. - If the change results in needing updates to docs (such as public API change, module interface etc), add a label for "needs docs" and inform the submitter they must submit a docs PR to update the appropriate area of Prebid.org **before the PR can merge**. Help them with finding where the docs are located on prebid.org if needed. + - Below are some examples of bidder specific updates that should require docs update (in their dev-docs/bidders/bidder.md file): + - Add support for GDPR consentManagement module > add `gdpr_supported: true` + - Add support for userId module > add `userId: pubCommon, digitrust, newProviderHere` + - Add support for video and/or native mediaTypes > add `media_types: video, native` + - Add support for COPPA > add `coppa_supported: true` - If all above is good, add a `LGTM` comment and request 1 additional core member to review. - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. From 3e4f799541497dd1c659b5d4ae2c5b5b81b3c708 Mon Sep 17 00:00:00 2001 From: Isaac Dettman Date: Tue, 16 Jul 2019 12:58:34 -0700 Subject: [PATCH 083/436] Kargo Adapter: fix extensible error (#3998) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * add '_sessionId' to the object literal for spec * removed error merge * replaced obj property with sibling variable * updated test for changes to sessionId --- modules/kargoBidAdapter.js | 9 ++++++--- test/spec/modules/kargoBidAdapter_spec.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 63406bf3ce4..74494ce66c9 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -5,6 +5,9 @@ const BIDDER_CODE = 'kargo'; const HOST = 'https://krk.kargo.com'; const SYNC = 'https://crb.kargo.com/api/v1/initsyncrnd/{UUID}?seed={SEED}&idx={INDEX}'; const SYNC_COUNT = 5; + +let sessionId; + export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -193,10 +196,10 @@ export const spec = { }, _getSessionId() { - if (!spec._sessionId) { - spec._sessionId = spec._generateRandomUuid(); + if (!sessionId) { + sessionId = spec._generateRandomUuid(); } - return spec._sessionId; + return sessionId; }, _generateRandomUuid() { diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 92f68fd9b91..7ff28a72c58 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -216,7 +216,7 @@ describe('kargo adapter tests', function () { } function getSessionId() { - return spec._sessionId; + return spec._getSessionId(); } function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { From d751dbdb5494862384fb839707eed436acad2845 Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Tue, 16 Jul 2019 23:19:16 +0300 Subject: [PATCH 084/436] Mgid Adapter: make placementId optional (#3992) --- modules/mgidBidAdapter.js | 16 +++-- test/spec/modules/mgidBidAdapter_spec.js | 86 +++++++++++++++++++++--- 2 files changed, 86 insertions(+), 16 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index c6744d28f45..c3f88106893 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -60,10 +60,10 @@ utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { - VERSION: '1.2', + VERSION: '1.3', code: BIDDER_CODE, supportedMediaTypes: [BANNER, NATIVE], - reId: /^[0-9]+$/, + reId: /^[1-9][0-9]*$/, NATIVE_ASSET_ID_TO_KEY_MAP: _NATIVE_ASSET_ID_TO_KEY_MAP, NATIVE_ASSET_KEY_TO_ASSET_MAP: _NATIVE_ASSET_KEY_TO_ASSET_MAP, /** @@ -102,10 +102,10 @@ export const spec = { bannerOk = sizes[f].length === 2; } } - return utils.isPlainObject(bid.params) && !!bid.params.accountId && !!bid.params.placementId && - utils.isStr(bid.params.accountId) && utils.isStr(bid.params.placementId) && - bid.params.accountId.toString().match(spec.reId) > 0 && bid.params.placementId.toString().match(spec.reId) && - (bannerOk || nativeOk); + let acc = Number(bid.params.accountId); + let plcmt = Number(bid.params.placementId); + return (bannerOk || nativeOk) && utils.isPlainObject(bid.params) && !!bid.adUnitCode && utils.isStr(bid.adUnitCode) && (plcmt > 0 ? bid.params.placementId.toString().search(spec.reId) === 0 : true) && + !!acc && acc > 0 && bid.params.accountId.toString().search(spec.reId) === 0; }, /** * Make a server request from the list of BidRequests. @@ -132,9 +132,11 @@ export const spec = { const secure = window.location.protocol === 'https:' ? 1 : 0; let imp = []; validBidRequests.forEach(bid => { + let tagid = utils.deepAccess(bid, 'params.placementId') || 0; + tagid = !tagid ? bid.adUnitCode : tagid + '/' + bid.adUnitCode; let impObj = { id: bid.bidId, - tagid: utils.deepAccess(bid, 'params.placementId'), + tagid, secure, }; const bidFloor = utils.deepAccess(bid, 'params.bidFloor') || utils.deepAccess(bid, 'params.bidfloor') || 0; diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 2b1a0739537..2216122da18 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -33,6 +33,7 @@ describe('Mgid bid adapter', function () { describe('isBidRequestValid', function () { let bid = { + 'adUnitCode': 'div', 'bidder': 'mgid', 'params': { 'property': '10433394', @@ -62,6 +63,7 @@ describe('Mgid bid adapter', function () { it('should return false when valid params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; + bid.adUnitCode = ''; bid.mediaTypes = { banner: { sizes: [[300, 250]] @@ -71,6 +73,32 @@ describe('Mgid bid adapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); + it('should return false when adUnitCode not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.adUnitCode = ''; + bid.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + bid.params = {accountId: 2, placementId: 1}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when valid params are passed as nums', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.adUnitCode = 'div'; + bid.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + bid.params = {accountId: 2, placementId: 1}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when valid params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; @@ -119,9 +147,10 @@ describe('Mgid bid adapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when valid params are passed', function () { + it('should return true when valid params are passed as strings', function () { let bid = Object.assign({}, bid); delete bid.params; + bid.adUnitCode = 'div'; bid.params = {accountId: '1', placementId: '1'}; bid.mediaTypes = { banner: { @@ -185,6 +214,7 @@ describe('Mgid bid adapter', function () { it('should return true when mediaTypes.native all assets needed', function () { let bid = Object.assign({}, bid); + bid.adUnitCode = 'div'; bid.params = {accountId: '2', placementId: '1'}; bid.mediaTypes = { native: { @@ -281,13 +311,46 @@ describe('Mgid bid adapter', function () { }); describe('buildRequests', function () { + it('should return undefined if no validBidRequests passed', function () { + expect(spec.buildRequests([])).to.be.undefined; + }); + let abid = { + adUnitCode: 'div', bidder: 'mgid', params: { accountId: '1', placementId: '2', }, }; + it('should return proper request url', function () { + localStorage.setItem('mgMuidn', 'xxx'); + let bid = Object.assign({}, abid); + bid.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + let bidRequests = [bid]; + const request = spec.buildRequests(bidRequests); + expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1?muid=xxx'); + localStorage.removeItem('mgMuidn') + }); + it('should proper handle gdpr', function () { + let bid = Object.assign({}, abid); + bid.mediaTypes = { + banner: { + sizes: [[300, 250]] + } + }; + let bidRequests = [bid]; + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'gdpr', gdprApplies: true}}); + expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); + expect(request.method).deep.equal('POST'); + const data = JSON.parse(request.data); + expect(data.user).deep.equal({ext: {consent: 'gdpr'}}); + expect(data.regs).deep.equal({ext: {gdpr: 1}}); + }); it('should return proper banner imp', function () { let bid = Object.assign({}, abid); bid.mediaTypes = { @@ -309,13 +372,13 @@ describe('Mgid bid adapter', function () { expect(data.device.h).equal(screenHeight); expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2'); + expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250, format: []}); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', }); }); it('should not return native imp if minimum asset list not requested', function () { @@ -357,13 +420,13 @@ describe('Mgid bid adapter', function () { expect(data.device.h).equal(screenHeight); expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2'); + expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}}); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":11,\"required\":0,\"data\":{\"type\":1}}]}}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":11,\"required\":0,\"data\":{\"type\":1}}]}}}]}', }); }); it('should return proper native imp with sponsoredBy', function () { @@ -392,13 +455,13 @@ describe('Mgid bid adapter', function () { expect(data.device.h).equal(screenHeight); expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2'); + expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 4, 'required': 0}], 'plcmtcnt': 1}}); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}}]}', }); }); it('should return proper banner request', function () { @@ -423,14 +486,14 @@ describe('Mgid bid adapter', function () { expect(data.device.h).equal(screenHeight); expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); - expect(data.imp[0].tagid).to.deep.equal('2'); + expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].banner).to.deep.equal({w: 300, h: 600, format: [{w: 300, h: 600}, {w: 300, h: 250}]}); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', }); }); }); @@ -565,6 +628,11 @@ describe('Mgid bid adapter', function () { }); }); + describe('getUserSyncs', function () { + it('should do nothing on getUserSyncs', function () { + spec.getUserSyncs() + }); + }); describe('on bidWon', function () { it('should replace nurl and burl for native', function () { const burl = 'burl&s=${' + 'AUCTION_PRICE}'; From 613b6fc9bc8b9b9085eee4f5a3f2ee76682f8492 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Wed, 17 Jul 2019 13:29:20 -0400 Subject: [PATCH 085/436] Google ad manager support for long-form video (#3787) * gam support * update gam module to use submodules pattern * Fix unit tests * bug fix: do not add bid if it is rejected and revert gulphelpers --- gulpHelpers.js | 1 - modules/.submodules.json | 3 +- modules/adpod.js | 163 ++++++++++-- modules/categoryTranslation.js | 2 +- modules/dfpAdServerVideo.js | 98 ++++++- modules/freeWheelAdserverVideo.js | 140 +--------- test/spec/modules/dfpAdServerVideo_spec.js | 246 +++++++++++++++++- .../modules/freeWheelAdserverVideo_spec.js | 34 ++- 8 files changed, 515 insertions(+), 172 deletions(-) diff --git a/gulpHelpers.js b/gulpHelpers.js index 04428133347..3814bd8f554 100644 --- a/gulpHelpers.js +++ b/gulpHelpers.js @@ -13,7 +13,6 @@ const BUILD_PATH = './build/dist'; const DEV_PATH = './build/dev'; const ANALYTICS_PATH = '../analytics'; - // get only subdirectories that contain package.json with 'main' property function isModuleDirectory(filePath) { try { diff --git a/modules/.submodules.json b/modules/.submodules.json index 097fe4b1f3b..c0e30037660 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -5,6 +5,7 @@ "criteortusIdSystem" ], "adpod": [ - "freeWheelAdserverVideo" + "freeWheelAdserverVideo", + "dfpAdServerVideo" ] } diff --git a/modules/adpod.js b/modules/adpod.js index 46671e9fb0a..c678c854dc1 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -22,6 +22,7 @@ import { config } from '../src/config'; import { ADPOD } from '../src/mediaTypes'; import Set from 'core-js/library/fn/set'; import find from 'core-js/library/fn/array/find'; +import { auctionManager } from '../src/auctionManager'; const from = require('core-js/library/fn/array/from'); @@ -215,21 +216,21 @@ export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAd if (!adServerCatId && brandCategoryExclusion) { utils.logWarn('Detected a bid without meta.adServerCatId while setConfig({adpod.brandCategoryExclusion}) was enabled. This bid has been rejected:', bidResponse) afterBidAdded(); - } - - if (config.getConfig('adpod.deferCaching') === false) { - bidCacheRegistry.addBid(bidResponse); - attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); - - updateBidQueue(auctionInstance, bidResponse, afterBidAdded); } else { - // generate targeting keys for bid - bidCacheRegistry.setupInitialCacheKey(bidResponse); - attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); + if (config.getConfig('adpod.deferCaching') === false) { + bidCacheRegistry.addBid(bidResponse); + attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); - // add bid to auction - addBidToAuction(auctionInstance, bidResponse); - afterBidAdded(); + updateBidQueue(auctionInstance, bidResponse, afterBidAdded); + } else { + // generate targeting keys for bid + bidCacheRegistry.setupInitialCacheKey(bidResponse); + attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); + + // add bid to auction + addBidToAuction(auctionInstance, bidResponse); + afterBidAdded(); + } } } else { fn.call(this, auctionInstance, bidResponse, afterBidAdded, bidderRequest); @@ -393,6 +394,7 @@ function initAdpodHooks() { } initAdpodHooks() + /** * * @param {Array[Object]} bids list of 'winning' bids that need to be cached @@ -431,11 +433,142 @@ export function sortByPricePerSecond(a, b) { return 0; } +/** + * This function returns targeting keyvalue pairs for long-form adserver modules. Freewheel and GAM are currently supporting Prebid long-form + * @param {Object} options + * @param {Array[string]} codes + * @param {function} callback + * @returns targeting kvs for adUnitCodes + */ +export function getTargeting({codes, callback} = {}) { + if (!callback) { + utils.logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); + return; + } + codes = codes || []; + const adPodAdUnits = getAdPodAdUnits(codes); + const bidsReceived = auctionManager.getBidsReceived(); + const competiveExclusionEnabled = config.getConfig('adpod.brandCategoryExclusion'); + const deferCachingSetting = config.getConfig('adpod.deferCaching'); + const deferCachingEnabled = (typeof deferCachingSetting === 'boolean') ? deferCachingSetting : true; + + let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); + bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; + bids.sort(sortByPricePerSecond); + + let targeting = {}; + if (deferCachingEnabled === false) { + adPodAdUnits.forEach((adUnit) => { + let adPodTargeting = []; + let adPodDurationSeconds = utils.deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + + bids + .filter((bid) => bid.adUnitCode === adUnit.code) + .forEach((bid, index, arr) => { + if (bid.video.durationBucket <= adPodDurationSeconds) { + adPodTargeting.push({ + [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + }); + adPodDurationSeconds -= bid.video.durationBucket; + } + if (index === arr.length - 1 && adPodTargeting.length > 0) { + adPodTargeting.push({ + [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + }); + } + }); + targeting[adUnit.code] = adPodTargeting; + }); + + callback(null, targeting); + } else { + let bidsToCache = []; + adPodAdUnits.forEach((adUnit) => { + let adPodDurationSeconds = utils.deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); + + bids + .filter((bid) => bid.adUnitCode === adUnit.code) + .forEach((bid) => { + if (bid.video.durationBucket <= adPodDurationSeconds) { + bidsToCache.push(bid); + adPodDurationSeconds -= bid.video.durationBucket; + } + }); + }); + + callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { + if (error) { + callback(error, null); + } else { + let groupedBids = utils.groupBy(bidsSuccessfullyCached, 'adUnitCode'); + Object.keys(groupedBids).forEach((adUnitCode) => { + let adPodTargeting = []; + + groupedBids[adUnitCode].forEach((bid, index, arr) => { + adPodTargeting.push({ + [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] + }); + + if (index === arr.length - 1 && adPodTargeting.length > 0) { + adPodTargeting.push({ + [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] + }); + } + }); + targeting[adUnitCode] = adPodTargeting; + }); + + callback(null, targeting); + } + }); + } + return targeting; +} + +/** + * This function returns the adunit of mediaType adpod + * @param {Array} codes adUnitCodes + * @returns {Array[Object]} adunits of mediaType adpod + */ +function getAdPodAdUnits(codes) { + return auctionManager.getAdUnits() + .filter((adUnit) => utils.deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) + .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true); +} + +/** + * This function removes bids of same category. It will be used when competitive exclusion is enabled. + * @param {Array[Object]} bidsReceived + * @returns {Array[Object]} unique category bids + */ +function getExclusiveBids(bidsReceived) { + let bids = bidsReceived + .map((bid) => Object.assign({}, bid, {[TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR]})); + bids = utils.groupBy(bids, TARGETING_KEY_PB_CAT_DUR); + let filteredBids = []; + Object.keys(bids).forEach((targetingKey) => { + bids[targetingKey].sort(utils.compareOn('responseTimestamp')); + filteredBids.push(bids[targetingKey][0]); + }); + return filteredBids; +} + +/** + * This function returns bids for adpod adunits + * @param {Array[Object]} bidsReceived + * @param {Array[Object]} adPodAdUnits + * @returns {Array[Object]} bids of mediaType adpod + */ +function getBidsForAdpod(bidsReceived, adPodAdUnits) { + let adUnitCodes = adPodAdUnits.map((adUnit) => adUnit.code); + return bidsReceived + .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD)) +} + const sharedMethods = { TARGETING_KEY_PB_CAT_DUR: TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID: TARGETING_KEY_CACHE_ID, - 'sortByPricePerSecond': sortByPricePerSecond, - 'callPrebidCacheAfterAuction': callPrebidCacheAfterAuction + 'getTargeting': getTargeting } Object.freeze(sharedMethods); diff --git a/modules/categoryTranslation.js b/modules/categoryTranslation.js index f4d0a281f57..091b16c8211 100644 --- a/modules/categoryTranslation.js +++ b/modules/categoryTranslation.js @@ -26,8 +26,8 @@ export const registerAdserver = hook('async', function(adServer) { let url; if (adServer === 'freewheel') { url = DEFAULT_TRANSLATION_FILE_URL; + initTranslation(url, DEFAULT_IAB_TO_FW_MAPPING_KEY); } - initTranslation(url, DEFAULT_IAB_TO_FW_MAPPING_KEY); }, 'registerAdserver'); registerAdserver(); diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 79c11c5c886..1614dbe6b0d 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -7,6 +7,8 @@ import { targeting } from '../src/targeting'; import { formatQS, format as buildUrl, parse } from '../src/url'; import { deepAccess, isEmpty, logError, parseSizesInput } from '../src/utils'; import { config } from '../src/config'; +import { getHook, submodule } from '../src/hook'; +import { auctionManager } from '../src/auctionManager'; /** * @typedef {Object} DfpVideoParams @@ -45,6 +47,8 @@ const defaultParamConstants = { unviewed_position_start: 1, }; +export const adpodUtils = {}; + /** * Merge all the bid data and publisher-supplied options into a single URL, and then return it. * @@ -56,7 +60,7 @@ const defaultParamConstants = { * (or the auction's winning bid for this adUnit, if undefined) compete alongside the rest of the * demand in DFP. */ -export default function buildDfpVideoUrl(options) { +export function buildDfpVideoUrl(options) { if (!options.params && !options.url) { logError(`A params object or a url is required to use $$PREBID_GLOBAL$$.adServers.dfp.buildVideoUrl`); return; @@ -103,6 +107,92 @@ export default function buildDfpVideoUrl(options) { }); } +export function notifyTranslationModule(fn) { + fn.call(this, 'dfp'); +} + +getHook('registerAdserver').before(notifyTranslationModule); + +/** + * @typedef {Object} DfpAdpodOptions + * + * @param {string} code Ad Unit code + * @param {Object} params Query params which should be set on the DFP request. + * These will override this module's defaults whenever they conflict. + * @param {function} callback Callback function to execute when master tag is ready + */ + +/** + * Creates master tag url for long-form + * @param {DfpAdpodOptions} options + * @returns {string} A URL which calls DFP with custom adpod targeting key values to compete with rest of the demand in DFP + */ +export function buildAdpodVideoUrl({code, params, callback} = {}) { + if (!params || !callback) { + logError(`A params object and a callback is required to use pbjs.adServers.dfp.buildAdpodVideoUrl`); + return; + } + + const derivedParams = { + correlator: Date.now(), + sz: getSizeForAdUnit(code), + url: encodeURIComponent(location.href), + }; + + function getSizeForAdUnit(code) { + let adUnit = auctionManager.getAdUnits() + .filter((adUnit) => adUnit.code === code) + let sizes = deepAccess(adUnit[0], 'mediaTypes.video.playerSize'); + return parseSizesInput(sizes).join('|'); + } + + adpodUtils.getTargeting({ + 'codes': [code], + 'callback': createMasterTag + }); + + function createMasterTag(err, targeting) { + if (err) { + callback(err, null); + return; + } + + let initialValue = { + [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: undefined, + [adpodUtils.TARGETING_KEY_CACHE_ID]: undefined + } + let customParams; + if (targeting[code]) { + customParams = targeting[code].reduce((acc, curValue) => { + if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_PB_CAT_DUR) { + acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] = (typeof acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] !== 'undefined') ? acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] + ',' + curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR] : curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR]; + } else if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_CACHE_ID) { + acc[adpodUtils.TARGETING_KEY_CACHE_ID] = curValue[adpodUtils.TARGETING_KEY_CACHE_ID] + } + return acc; + }, initialValue); + } + + let encodedCustomParams = encodeURIComponent(formatQS(customParams)); + + const queryParams = Object.assign({}, + defaultParamConstants, + derivedParams, + params, + { cust_params: encodedCustomParams } + ); + + const masterTag = buildUrl({ + protocol: 'https', + host: 'pubads.g.doubleclick.net', + pathname: '/gampad/ads', + search: queryParams + }); + + callback(null, masterTag); + } +} + /** * Builds a video url from a base dfp video url and a winning bid, appending * Prebid-specific key-values. @@ -170,5 +260,9 @@ function getCustParams(bid, options) { } registerVideoSupport('dfp', { - buildVideoUrl: buildDfpVideoUrl + buildVideoUrl: buildDfpVideoUrl, + buildAdpodVideoUrl: buildAdpodVideoUrl, + getAdpodTargeting: (args) => adpodUtils.getTargeting(args) }); + +submodule('adpod', adpodUtils); diff --git a/modules/freeWheelAdserverVideo.js b/modules/freeWheelAdserverVideo.js index a93e5ab9159..03217b1165d 100644 --- a/modules/freeWheelAdserverVideo.js +++ b/modules/freeWheelAdserverVideo.js @@ -3,153 +3,17 @@ */ import { registerVideoSupport } from '../src/adServerManager'; -import { auctionManager } from '../src/auctionManager'; -import { groupBy, deepAccess, logError, compareOn } from '../src/utils'; -import { config } from '../src/config'; -import { ADPOD } from '../src/mediaTypes'; import { getHook, submodule } from '../src/hook'; +export const adpodUtils = {}; export function notifyTranslationModule(fn) { fn.call(this, 'freewheel'); } getHook('registerAdserver').before(notifyTranslationModule); -/** - * This function returns targeting keyvalue pairs for freewheel adserver module - * @param {Object} options - * @param {Array[string]} codes - * @param {function} callback - * @returns targeting kvs for adUnitCodes - */ -export function getTargeting({codes, callback} = {}) { - if (!callback) { - logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); - return; - } - codes = codes || []; - const adPodAdUnits = getAdPodAdUnits(codes); - const bidsReceived = auctionManager.getBidsReceived(); - const competiveExclusionEnabled = config.getConfig('adpod.brandCategoryExclusion'); - const deferCachingSetting = config.getConfig('adpod.deferCaching'); - const deferCachingEnabled = (typeof deferCachingSetting === 'boolean') ? deferCachingSetting : true; - - let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); - bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; - bids.sort(adpodUtils.sortByPricePerSecond); - - let targeting = {}; - if (deferCachingEnabled === false) { - adPodAdUnits.forEach((adUnit) => { - let adPodTargeting = []; - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); - - bids - .filter((bid) => bid.adUnitCode === adUnit.code) - .forEach((bid, index, arr) => { - if (bid.video.durationBucket <= adPodDurationSeconds) { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR] - }); - adPodDurationSeconds -= bid.video.durationBucket; - } - if (index === arr.length - 1 && adPodTargeting.length > 0) { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID] - }); - } - }); - targeting[adUnit.code] = adPodTargeting; - }); - - callback(null, targeting); - } else { - let bidsToCache = []; - adPodAdUnits.forEach((adUnit) => { - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); - - bids - .filter((bid) => bid.adUnitCode === adUnit.code) - .forEach((bid) => { - if (bid.video.durationBucket <= adPodDurationSeconds) { - bidsToCache.push(bid); - adPodDurationSeconds -= bid.video.durationBucket; - } - }); - }); - - adpodUtils.callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) { - if (error) { - callback(error, null); - } else { - let groupedBids = groupBy(bidsSuccessfullyCached, 'adUnitCode'); - Object.keys(groupedBids).forEach((adUnitCode) => { - let adPodTargeting = []; - - groupedBids[adUnitCode].forEach((bid, index, arr) => { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR] - }); - - if (index === arr.length - 1 && adPodTargeting.length > 0) { - adPodTargeting.push({ - [adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID] - }); - } - }); - targeting[adUnitCode] = adPodTargeting; - }); - - callback(null, targeting); - } - }); - } - return targeting; -} - -/** - * This function returns the adunit of mediaType adpod - * @param {Array} codes adUnitCodes - * @returns {Array[Object]} adunits of mediaType adpod - */ -function getAdPodAdUnits(codes) { - return auctionManager.getAdUnits() - .filter((adUnit) => deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) - .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) != -1 : true); -} - -/** - * This function removes bids of same freewheel category. It will be used when competitive exclusion is enabled. - * @param {Array[Object]} bidsReceived - * @returns {Array[Object]} unique freewheel category bids - */ -function getExclusiveBids(bidsReceived) { - let bids = bidsReceived - .map((bid) => Object.assign({}, bid, {[adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR]})); - bids = groupBy(bids, adpodUtils.TARGETING_KEY_PB_CAT_DUR); - let filteredBids = []; - Object.keys(bids).forEach((targetingKey) => { - bids[targetingKey].sort(compareOn('responseTimestamp')); - filteredBids.push(bids[targetingKey][0]); - }); - return filteredBids; -} - -/** - * This function returns bids for adpod adunits - * @param {Array[Object]} bidsReceived - * @param {Array[Object]} adPodAdUnits - * @returns {Array[Object]} bids of mediaType adpod - */ -function getBidsForAdpod(bidsReceived, adPodAdUnits) { - let adUnitCodes = adPodAdUnits.map((adUnit) => adUnit.code); - return bidsReceived - .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD)) -} - registerVideoSupport('freewheel', { - getTargeting: getTargeting + getTargeting: (args) => adpodUtils.getTargeting(args) }); -export const adpodUtils = {}; submodule('adpod', adpodUtils); diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 30cf91c2e17..62b0a752f50 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -1,12 +1,14 @@ import { expect } from 'chai'; import parse from 'url-parse'; -import buildDfpVideoUrl from 'modules/dfpAdServerVideo'; +import { buildDfpVideoUrl, buildAdpodVideoUrl } from 'modules/dfpAdServerVideo'; import { parseQS } from 'src/url'; import adUnit from 'test/fixtures/video/adUnit'; import * as utils from 'src/utils'; import { config } from 'src/config'; import { targeting } from 'src/targeting'; +import { auctionManager } from 'src/auctionManager'; +import * as adpod from 'modules/adpod'; const bid = { videoCacheKey: 'abc', @@ -296,4 +298,246 @@ describe('The DFP video support module', function () { expect(customParams).to.have.property('hb_uuid', 'def'); expect(customParams).to.have.property('hb_cache_id', 'def'); }); + + describe('adpod unit tests', function () { + let amStub; + let amGetAdUnitsStub; + let xhr; + let requests; + + before(function () { + let adUnits = [{ + code: 'adUnitCode-1', + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480], + adPodDurationSec: 60, + durationRangeSec: [15, 30], + requireExactDuration: true + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 14542875, + } + } + ] + }]; + + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); + amGetAdUnitsStub.returns(adUnits); + amStub = sinon.stub(auctionManager, 'getBidsReceived'); + }); + + beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + + config.setConfig({ + adpod: { + brandCategoryExclusion: true, + deferCaching: false + } + }); + }) + + afterEach(function() { + config.resetConfig(); + xhr.restore(); + }); + + after(function () { + amGetAdUnitsStub.restore(); + amStub.restore(); + }); + + it('should return masterTag url', function() { + amStub.returns(getBidsReceived()); + let url; + parse(buildAdpodVideoUrl({ + code: 'adUnitCode-1', + callback: handleResponse, + params: { + 'iu': 'my/adUnit', + 'description_url': 'someUrl.com', + } + })); + + function handleResponse(err, masterTag) { + if (err) { + return; + } + url = parse(masterTag); + + expect(url.protocol).to.equal('https:'); + expect(url.host).to.equal('pubads.g.doubleclick.net'); + + const queryParams = parseQS(url.query); + expect(queryParams).to.have.property('correlator'); + expect(queryParams).to.have.property('description_url', 'someUrl.com'); + expect(queryParams).to.have.property('env', 'vp'); + expect(queryParams).to.have.property('gdfp_req', '1'); + expect(queryParams).to.have.property('iu', 'my/adUnit'); + expect(queryParams).to.have.property('output', 'xml_vast3'); + expect(queryParams).to.have.property('sz', '640x480'); + expect(queryParams).to.have.property('unviewed_position_start', '1'); + expect(queryParams).to.have.property('url'); + expect(queryParams).to.have.property('cust_params'); + + const custParams = parseQS(decodeURIComponent(queryParams.cust_params)); + expect(custParams).to.have.property('hb_cache_id', '123'); + expect(custParams).to.have.property('hb_pb_cat_dur', '15.00_395_15s,15.00_406_30s,10.00_395_15s'); + } + }); + + it('should return masterTag url with correct custom params when brandCategoryExclusion is false', function() { + config.setConfig({ + adpod: { + brandCategoryExclusion: false, + } + }); + function getBids() { + let bids = [ + createBid(10, 'adUnitCode-1', 15, '10.00_15s', '123', '395'), + createBid(15, 'adUnitCode-1', 15, '15.00_15s', '123', '395'), + createBid(25, 'adUnitCode-1', 30, '15.00_30s', '123', '406'), + ]; + bids.forEach((bid) => { + delete bid.meta; + }); + return bids; + } + amStub.returns(getBids()); + let url; + parse(buildAdpodVideoUrl({ + code: 'adUnitCode-1', + callback: handleResponse, + params: { + 'iu': 'my/adUnit', + 'description_url': 'someUrl.com', + } + })); + + function handleResponse(err, masterTag) { + if (err) { + return; + } + url = parse(masterTag); + expect(url.protocol).to.equal('https:'); + expect(url.host).to.equal('pubads.g.doubleclick.net'); + + const queryParams = parseQS(url.query); + expect(queryParams).to.have.property('correlator'); + expect(queryParams).to.have.property('description_url', 'someUrl.com'); + expect(queryParams).to.have.property('env', 'vp'); + expect(queryParams).to.have.property('gdfp_req', '1'); + expect(queryParams).to.have.property('iu', 'my/adUnit'); + expect(queryParams).to.have.property('output', 'xml_vast3'); + expect(queryParams).to.have.property('sz', '640x480'); + expect(queryParams).to.have.property('unviewed_position_start', '1'); + expect(queryParams).to.have.property('url'); + expect(queryParams).to.have.property('cust_params'); + + const custParams = parseQS(decodeURIComponent(queryParams.cust_params)); + expect(custParams).to.have.property('hb_cache_id', '123'); + expect(custParams).to.have.property('hb_pb_cat_dur', '10.00_15s,15.00_15s,15.00_30s'); + } + }); + + it('should handle error when cache fails', function() { + config.setConfig({ + adpod: { + brandCategoryExclusion: true, + deferCaching: true + } + }); + amStub.returns(getBidsReceived()); + + parse(buildAdpodVideoUrl({ + code: 'adUnitCode-1', + callback: handleResponse, + params: { + 'iu': 'my/adUnit', + 'description_url': 'someUrl.com', + } + })); + + requests[0].respond(503, { + 'Content-Type': 'plain/text', + }, 'The server could not save anything at the moment.'); + + function handleResponse(err, masterTag) { + expect(masterTag).to.be.null; + expect(err).to.be.an('error'); + } + }); + }) }); + +function getBidsReceived() { + return [ + createBid(10, 'adUnitCode-1', 15, '10.00_395_15s', '123', '395'), + createBid(15, 'adUnitCode-1', 15, '15.00_395_15s', '123', '395'), + createBid(25, 'adUnitCode-1', 30, '15.00_406_30s', '123', '406'), + ] +} + +function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, label) { + return { + 'bidderCode': 'appnexus', + 'width': 640, + 'height': 360, + 'statusMessage': 'Bid available', + 'adId': '28f24ced14586c', + 'mediaType': 'video', + 'source': 'client', + 'requestId': '28f24ced14586c', + 'cpm': cpm, + 'creativeId': 97517771, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 3600, + 'adUnitCode': adUnitCode, + 'video': { + 'context': 'adpod', + 'durationBucket': durationBucket + }, + 'appnexus': { + 'buyerMemberId': 9325 + }, + 'vastUrl': 'http://some-vast-url.com', + 'vastImpUrl': 'http://some-vast-imp-url.com', + 'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b', + 'responseTimestamp': 1548442460888, + 'requestTimestamp': 1548442460827, + 'bidder': 'appnexus', + 'timeToRespond': 61, + 'pbLg': '5.00', + 'pbMg': '5.00', + 'pbHg': '5.00', + 'pbAg': '5.00', + 'pbDg': '5.00', + 'pbCg': '', + 'size': '640x360', + 'adserverTargeting': { + 'hb_bidder': 'appnexus', + 'hb_adid': '28f24ced14586c', + 'hb_pb': '5.00', + 'hb_size': '640x360', + 'hb_source': 'client', + 'hb_format': 'video', + 'hb_pb_cat_dur': priceIndustryDuration, + 'hb_cache_id': uuid + }, + 'customCacheKey': `${priceIndustryDuration}_${uuid}`, + 'meta': { + 'iabSubCatId': 'iab-1', + 'adServerCatId': label + }, + 'videoCacheKey': '4cf395af-8fee-4960-af0e-88d44e399f14' + } +} diff --git a/test/spec/modules/freeWheelAdserverVideo_spec.js b/test/spec/modules/freeWheelAdserverVideo_spec.js index ffc690e5a92..f958a2733db 100644 --- a/test/spec/modules/freeWheelAdserverVideo_spec.js +++ b/test/spec/modules/freeWheelAdserverVideo_spec.js @@ -1,12 +1,13 @@ import { expect } from 'chai'; -import { getTargeting, adpodUtils } from 'modules/freeWheelAdserverVideo'; +import { adpodUtils } from 'modules/freeWheelAdserverVideo'; import { auctionManager } from 'src/auctionManager'; import { config } from 'src/config'; describe('freeWheel adserver module', function() { let amStub; let amGetAdUnitsStub; - let pbcStub; + let xhr; + let requests; before(function () { let adUnits = [{ @@ -52,12 +53,13 @@ describe('freeWheel adserver module', function() { amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); amGetAdUnitsStub.returns(adUnits); amStub = sinon.stub(auctionManager, 'getBidsReceived'); - pbcStub = sinon.stub(adpodUtils, 'callPrebidCacheAfterAuction').callsFake(function (...args) { - args[1](null, getBidsReceived()); - }); }); beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + config.setConfig({ adpod: { brandCategoryExclusion: false, @@ -68,6 +70,7 @@ describe('freeWheel adserver module', function() { afterEach(function() { config.resetConfig(); + xhr.restore(); }); after(function () { @@ -78,7 +81,7 @@ describe('freeWheel adserver module', function() { it('should return targeting for all adunits', function() { amStub.returns(getBidsReceived()); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -91,7 +94,7 @@ describe('freeWheel adserver module', function() { it('should return targeting for passed adunit code', function() { amStub.returns(getBidsReceived()); let targeting; - getTargeting({ + adpodUtils.getTargeting({ codes: ['preroll_1'], callback: function(errorMsg, targetingResult) { targeting = targetingResult; @@ -120,7 +123,7 @@ describe('freeWheel adserver module', function() { }]; amStub.returns(getBidsReceived().concat(bannerBid)); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -144,7 +147,7 @@ describe('freeWheel adserver module', function() { createBid(10, 'preroll_1', 30, '10.00_395_30s', '123', '395') ]); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -161,7 +164,7 @@ describe('freeWheel adserver module', function() { createBid(15, 'midroll_1', 90, '15.00_406_90s', '123', '406') ]); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } @@ -179,15 +182,20 @@ describe('freeWheel adserver module', function() { }); amStub.returns(getBidsReceived()); let targeting; - getTargeting({ + adpodUtils.getTargeting({ callback: function(errorMsg, targetingResult) { targeting = targetingResult; } }); - expect(pbcStub.called).to.equal(true); + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify({'responses': getBidsReceived().slice(0, 4)}) + ); + expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['midroll_1'].length).to.equal(4); + expect(targeting['midroll_1'].length).to.equal(3); }); }); From a7383c068eeb2837a6f1c31132fd6cb2334342f2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 17 Jul 2019 13:34:03 -0400 Subject: [PATCH 086/436] Prebid 2.24.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ca8c03783d..11e9b857234 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.24.0-pre", + "version": "2.24.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3fdc91d6035bccb9b5061f8eced922cb886cd493 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 17 Jul 2019 13:50:53 -0400 Subject: [PATCH 087/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11e9b857234..1cc2da9abc2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.24.0", + "version": "2.25.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 3252a7f67c9e1522467d55676114513706099f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Fri, 19 Jul 2019 15:11:00 +0200 Subject: [PATCH 088/436] Added 'ceh' config property in Criteo bid adapter (#3969) * Added 'ceh' config property and mapped it to CDB request Added 'ceh' config property and mapped it to CDB request * Added config.resetConfig() to ensure that call to setConfig won't have an impact on any other test * Missed the ';' --- modules/criteoBidAdapter.js | 9 ++++++- modules/criteoBidAdapter.md | 10 ++++++++ test/spec/modules/criteoBidAdapter_spec.js | 28 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index ff612aff905..0507ba428be 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -5,8 +5,9 @@ import * as utils from '../src/utils'; import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; +import { config } from '../src/config'; -const ADAPTER_VERSION = 16; +const ADAPTER_VERSION = 17; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -47,6 +48,8 @@ export const spec = { let url; let data; + Object.assign(bidderRequest, { ceh: config.getConfig('criteo.ceh') }); + // If publisher tag not already loaded try to get it from fast bid if (!publisherTagAvailable()) { window.Criteo = window.Criteo || {}; @@ -239,6 +242,10 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (networkId) { request.publisher.networkid = networkId; } + request.user = {}; + if (bidderRequest && bidderRequest.ceh) { + request.user.ceh = bidderRequest.ceh; + } if (bidderRequest && bidderRequest.gdprConsent) { request.gdprConsent = {}; if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { diff --git a/modules/criteoBidAdapter.md b/modules/criteoBidAdapter.md index 796c70a980f..e4c441c758d 100644 --- a/modules/criteoBidAdapter.md +++ b/modules/criteoBidAdapter.md @@ -25,3 +25,13 @@ Module that connects to Criteo's demand sources. } ]; ``` + +# Additional Config (Optional) +Set the "ceh" property to provides the user's hashed email if available +``` + pbjs.setConfig({ + criteo: { + ceh: 'hashed mail' + } + }); +``` \ No newline at end of file diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 8a5bea97cb8..ac9ae53af07 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -3,12 +3,14 @@ import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; +import { config } from '../../../src/config'; describe('The Criteo bidding adapter', function () { beforeEach(function () { // Remove FastBid to avoid side effects. localStorage.removeItem('criteo_fast_bid'); }); + describe('isBidRequestValid', function () { it('should return false when given an invalid bid', function () { const bid = { @@ -66,6 +68,10 @@ describe('The Criteo bidding adapter', function () { }, }; + afterEach(function () { + config.resetConfig(); + }); + it('should properly build a zoneId request', function () { const bidRequests = [ { @@ -198,6 +204,28 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.gdprConsent.gdprApplies).to.equal(undefined); expect(ortbRequest.gdprConsent.consentGiven).to.equal(undefined); }); + + it('should properly build a request with ceh', function () { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: { + zoneId: 123, + }, + }, + ]; + config.setConfig({ + criteo: { + ceh: 'hashedemail' + } + }); + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.user).to.not.be.null; + expect(request.data.user.ceh).to.equal('hashedemail'); + }); }); describe('interpretResponse', function () { From 7f6d1924e41d5e9acddd063182d712390ebf7104 Mon Sep 17 00:00:00 2001 From: afsheenb Date: Fri, 19 Jul 2019 09:21:58 -0400 Subject: [PATCH 089/436] ozone adapter - minor fix to add w/h to video requests (#3953) * minor fix to add w/h to video requests * fixing padding/spacing errors caught by circleCI * fixing padding/spacing errors caught by circleCI, take two --- modules/ozoneBidAdapter.js | 91 ++++++++++++++++++++--- test/spec/modules/ozoneBidAdapter_spec.js | 89 +++++++++++++++++++++- 2 files changed, 167 insertions(+), 13 deletions(-) diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 7ab69f1e37a..9bd4f21ff96 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -11,7 +11,7 @@ const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js'; -const OZONEVERSION = '2.1.1'; +const OZONEVERSION = '2.1.2'; export const spec = { code: BIDDER_CODE, @@ -65,11 +65,11 @@ export const spec = { } if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) { if (!bid.mediaTypes.video.hasOwnProperty('context')) { - utils.logInfo('OZONE: [WARNING] No context key/value in bid. Rejecting bid: ', ozoneBidRequest); + utils.logInfo('OZONE: [WARNING] No context key/value in bid. Rejecting bid: ', bid); return false; } if (bid.mediaTypes.video.context !== 'outstream') { - utils.logInfo('OZONE: [WARNING] Only outstream video is supported. Rejecting bid: ', ozoneBidRequest); + utils.logInfo('OZONE: [WARNING] Only outstream video is supported. Rejecting bid: ', bid); return false; } } @@ -134,10 +134,24 @@ export const spec = { arrBannerSizes = ozoneBidRequest.mediaTypes[BANNER].sizes; /* Note - if there is a sizes element in the config root it will be pushed into here */ utils.logInfo('OZONE: setting banner size from the mediaTypes.banner element for bidId ' + obj.id + ': ', arrBannerSizes); } - // Video integration is not complete yet if (ozoneBidRequest.mediaTypes.hasOwnProperty(VIDEO)) { obj.video = ozoneBidRequest.mediaTypes[VIDEO]; - utils.logInfo('OZONE: setting video object from the mediaTypes.video element: ' + obj.id + ':', obj.video); + // we need to duplicate some of the video values + let wh = getWidthAndHeightFromVideoObject(obj.video); + utils.logInfo('OZONE: setting video object from the mediaTypes.video element: ' + obj.id + ':', obj.video, 'wh=', wh); + if (wh && typeof wh === 'object') { + obj.video.w = wh['w']; + obj.video.h = wh['h']; + if (playerSizeIsNestedArray(obj.video)) { // this should never happen; it was in the original spec for this change though. + utils.logInfo('OZONE: setting obj.video.format to be an array of objects'); + obj.video.format = [wh]; + } else { + utils.logInfo('OZONE: setting obj.video.format to be an object'); + obj.video.format = wh; + } + } else { + utils.logInfo('OZONE: cannot set w, h & format values for video; the config is not right'); + } } // Native integration is not complete yet if (ozoneBidRequest.mediaTypes.hasOwnProperty(NATIVE)) { @@ -319,7 +333,7 @@ export function checkDeepArray(Arr) { } export function defaultSize(thebidObj) { if (!thebidObj) { - utils.logInfo('defaultSize received empty bid obj! going to return fixed default size'); + utils.logInfo('OZONE: defaultSize received empty bid obj! going to return fixed default size'); return { 'defaultHeight': 250, 'defaultWidth': 300 @@ -389,14 +403,14 @@ export function getRoundedBid(price, mediaType) { let theConfigObject = getGranularityObject(mediaType, mediaTypeGranularity, strBuckets, objBuckets); let theConfigKey = getGranularityKeyName(mediaType, mediaTypeGranularity, strBuckets); - utils.logInfo('getRoundedBid. price:', price, 'mediaType:', mediaType, 'configkey:', theConfigKey, 'configObject:', theConfigObject, 'mediaTypeGranularity:', mediaTypeGranularity, 'strBuckets:', strBuckets); + utils.logInfo('OZONE: getRoundedBid. price:', price, 'mediaType:', mediaType, 'configkey:', theConfigKey, 'configObject:', theConfigObject, 'mediaTypeGranularity:', mediaTypeGranularity, 'strBuckets:', strBuckets); let priceStringsObj = getPriceBucketString( price, theConfigObject, config.getConfig('currency.granularityMultiplier') ); - utils.logInfo('priceStringsObj', priceStringsObj); + utils.logInfo('OZONE: priceStringsObj', priceStringsObj); // by default, without any custom granularity set, you get granularity name : 'medium' let granularityNamePriceStringsKeyMapping = { 'medium': 'med', @@ -526,9 +540,68 @@ function outstreamRender(bid) { function toFlatArray(obj) { let ret = []; Object.keys(obj).forEach(function(key) { if (obj[key]) { ret.push(parseInt(key)); } }); - utils.logInfo('toFlatArray:', obj, 'returning', ret); + utils.logInfo('OZONE: toFlatArray:', obj, 'returning', ret); return ret; } +/** + * + * @param objVideo will be like {"playerSize":[640,480],"mimes":["video/mp4"],"context":"outstream"} or POSSIBLY {"playerSize":[[640,480]],"mimes":["video/mp4"],"context":"outstream"} + * @return object {w,h} or null + */ +export function getWidthAndHeightFromVideoObject(objVideo) { + let playerSize = getPlayerSizeFromObject(objVideo); + if (!playerSize) { + return null; + } + if (playerSize[0] && typeof playerSize[0] === 'object') { + utils.logInfo('OZONE: getWidthAndHeightFromVideoObject found nested array inside playerSize.', playerSize[0]); + playerSize = playerSize[0]; + if (typeof playerSize[0] !== 'number' && typeof playerSize[0] !== 'string') { + utils.logInfo('OZONE: getWidthAndHeightFromVideoObject found non-number/string type inside the INNER array in playerSize. This is totally wrong - cannot continue.', playerSize[0]); + return null; + } + } + if (playerSize.length !== 2) { + utils.logInfo('OZONE: getWidthAndHeightFromVideoObject found playerSize with length of ' + playerSize.length + '. This is totally wrong - cannot continue.'); + return null; + } + return ({'w': playerSize[0], 'h': playerSize[1]}); +} + +/** + * @param objVideo will be like {"playerSize":[640,480],"mimes":["video/mp4"],"context":"outstream"} or POSSIBLY {"playerSize":[[640,480]],"mimes":["video/mp4"],"context":"outstream"} + * @return object {w,h} or null + */ +export function playerSizeIsNestedArray(objVideo) { + let playerSize = getPlayerSizeFromObject(objVideo); + if (!playerSize) { + return null; + } + if (playerSize.length < 1) { + return null; + } + return (playerSize[0] && typeof playerSize[0] === 'object'); +} + +/** + * Common functionality when looking at a video object, to get the playerSize + * @param objVideo + * @returns {*} + */ +function getPlayerSizeFromObject(objVideo) { + utils.logInfo('OZONE: getPlayerSizeFromObject received object', objVideo); + if (!objVideo.hasOwnProperty('playerSize')) { + utils.logError('OZONE: getPlayerSizeFromObject FAILED: no playerSize in video object', objVideo); + return null; + } + let playerSize = objVideo.playerSize; + if (typeof playerSize !== 'object') { + utils.logError('OZONE: getPlayerSizeFromObject FAILED: playerSize is not an object/array', objVideo); + return null; + } + return playerSize; +} + registerBidder(spec); utils.logInfo('OZONE: ozoneBidAdapter ended'); diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index e17d51804a1..a0b51ff7a9f 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/ozoneBidAdapter'; +import { spec, getWidthAndHeightFromVideoObject, playerSizeIsNestedArray, defaultSize } from 'modules/ozoneBidAdapter'; import { config } from 'src/config'; import {Renderer} from '../../../src/Renderer'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; @@ -74,7 +74,7 @@ var validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo = [ bidderRequestId: '1c1586b27a1b5c8', crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, params: { publisherId: '9876abcd12-3', customData: {'gender': 'bart', 'age': 'low'}, lotameData: {'Profile': {'tpid': 'c8ef27a0d4ba771a81159f0d2e792db4', 'Audiences': {'Audience': [{'id': '99999', 'abbr': 'sports'}, {'id': '88888', 'abbr': 'movie'}, {'id': '77777', 'abbr': 'blogger'}], 'ThirdPartyAudience': [{'id': '123', 'name': 'Automobiles'}, {'id': '456', 'name': 'Ages: 30-39'}]}}}, placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, - mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream'}, native: {info: 'dummy data'}}, + mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream', 'sizes': [640, 480]}, native: {info: 'dummy data'}}, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -664,7 +664,7 @@ describe('ozone Adapter', function () { params: { 'placementId': '1234567890', 'publisherId': '9876abcd12-3', - 'lotameData': 'this should be an object', + 'lotameData': {}, siteId: '1234567890' }, mediaTypes: { @@ -678,6 +678,24 @@ describe('ozone Adapter', function () { expect(spec.isBidRequestValid(xBadVideoContext)).to.equal(false); }); + var xBadVideoContext2 = { + bidder: BIDDER_CODE, + params: { + 'placementId': '1234567890', + 'publisherId': '9876abcd12-3', + 'lotameData': {}, + siteId: '1234567890' + }, + mediaTypes: { + video: { + mimes: ['video/mp4']} + } + }; + + it('should not validate video without context attribute', function () { + expect(spec.isBidRequestValid(xBadVideoContext2)).to.equal(false); + }); + let validVideoBidReq = { bidder: BIDDER_CODE, params: { @@ -692,7 +710,7 @@ describe('ozone Adapter', function () { } }; - it('should not validate video instream being sent', function () { + it('should validate video outstream being sent', function () { expect(spec.isBidRequestValid(validVideoBidReq)).to.equal(true); }); }); @@ -908,4 +926,67 @@ describe('ozone Adapter', function () { expect(result).to.be.empty; }); }); + + describe('video object utils', function () { + it('should find width & height from video object', function () { + let obj = {'playerSize': [640, 480], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result.w).to.equal(640); + expect(result.h).to.equal(480); + }); + it('should find null from bad video object', function () { + let obj = {'playerSize': [], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object2', function () { + let obj = {'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object3', function () { + let obj = {'playerSize': 'should be an array', 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find that player size is nested', function () { + let obj = {'playerSize': [[640, 480]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result.w).to.equal(640); + expect(result.h).to.equal(480); + }); + it('should fail if player size is 2 x nested', function () { + let obj = {'playerSize': [[[640, 480]]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = getWidthAndHeightFromVideoObject(obj); + expect(result).to.be.null; + }); + it('should find that player size is nested', function () { + let obj = {'playerSize': [[640, 480]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.true; + }); + it('should find null from bad video object', function () { + let obj = {'playerSize': [], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object2', function () { + let obj = {'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.null; + }); + it('should find null from bad video object3', function () { + let obj = {'playerSize': 'should be an array', 'mimes': ['video/mp4'], 'context': 'outstream'}; + const result = playerSizeIsNestedArray(obj); + expect(result).to.be.null; + }); + }); + describe('default size', function () { + it('should should return default sizes if no obj is sent', function () { + let obj = ''; + const result = defaultSize(obj); + expect(result.defaultHeight).to.equal(250); + expect(result.defaultWidth).to.equal(300); + }); + }); }); From 3ffcc0f2e90036f835735d956a0aa099ed2a0642 Mon Sep 17 00:00:00 2001 From: rhythmonebhaines <49991465+rhythmonebhaines@users.noreply.github.com> Date: Fri, 19 Jul 2019 06:33:11 -0700 Subject: [PATCH 090/436] Rhythmone Adapter - Remove usersync, do not send device, do not send bad banners (#3927) --- modules/rhythmoneBidAdapter.js | 103 +++++------------- test/spec/modules/rhythmoneBidAdapter_spec.js | 90 ++++++++------- 2 files changed, 68 insertions(+), 125 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 6e7a935c71c..84caca5508a 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -15,8 +15,7 @@ function RhythmOneBidAdapter() { let SUPPORTED_VIDEO_API = [1, 2, 5]; let slotsToBids = {}; let that = this; - let version = '2.0.0.0'; - let loadStart = Date.now(); + let version = '2.0.1.0'; var win = typeof window !== 'undefined' ? window : {}; this.isBidRequestValid = function (bid) { @@ -24,66 +23,11 @@ function RhythmOneBidAdapter() { }; this.getUserSyncs = function (syncOptions, responses, gdprConsent) { - let slots = []; - let placementIds = []; - - for (let k in slotsToBids) { - slots.push(k); - placementIds.push(getFirstParam('placementId', [slotsToBids[k]])); - } - - let data = { - doc_version: 1, - doc_type: 'Prebid Audit', - placement_id: placementIds.join(',').replace(/[,]+/g, ',').replace(/^,|,$/g, '') - }; - let w = typeof (window) !== 'undefined' ? window : {document: {location: {href: ''}}}; - let ao = w.document.location.ancestorOrigins; - let q = []; - let u = '//hbevents.1rx.io/audit?'; - - if (ao && ao.length > 0) { - data.ancestor_origins = ao[ao.length - 1]; - } - - data.popped = w.opener !== null ? 1 : 0; - data.framed = w.top === w ? 0 : 1; - - try { - data.url = w.top.document.location.href.toString(); - } catch (ex) { - data.url = w.document.location.href.toString(); - } - - try { - data.prebid_version = '$prebid.version$'; - data.prebid_timeout = config.getConfig('bidderTimeout'); - } catch (ex) { } - - data.response_ms = Date.now() - loadStart; - data.placement_codes = slots.join(','); - data.bidder_version = version; - if (gdprConsent) { - data.gdpr_consent = gdprConsent.consentString; - data.gdpr = (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; - } - - for (let k in data) { - q.push(encodeURIComponent(k) + '=' + encodeURIComponent((typeof data[k] === 'object' ? JSON.stringify(data[k]) : data[k]))); - } - - q.sort(); - - if (syncOptions.pixelEnabled) { - return [{ - type: 'image', - url: u + q.join('&') - }]; - } + return []; }; function frameImp(BRs) { - var imp = []; + var impList = []; for (var i = 0; i < BRs.length; i++) { slotsToBids[BRs[i].adUnitCode || BRs[i].placementCode] = BRs[i]; var impObj = {}; @@ -92,15 +36,21 @@ function RhythmOneBidAdapter() { impObj.secure = win.location.protocol === 'https:' ? 1 : 0; if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { - impObj.banner = frameBanner(BRs[i]); + let banner = frameBanner(BRs[i]); + if (banner) { + impObj.banner = banner; + } } if (utils.deepAccess(BRs[i], 'mediaTypes.video') || utils.deepAccess(BRs[i], 'mediaType') === 'video') { impObj.video = frameVideo(BRs[i]); } + if (!(impObj.banner || impObj.video)) { + continue; + } impObj.ext = frameExt(BRs[i]); - imp.push(impObj); + impList.push(impObj); } - return imp; + return impList; } function frameSite(bidderRequest) { @@ -134,7 +84,6 @@ function RhythmOneBidAdapter() { function frameDevice() { return { ua: navigator.userAgent, - devicetype: /(ios|ipod|ipad|iphone|android)/i.test(win.navigator.userAgent) ? 1 : /(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i.test(win.navigator.userAgent) ? 3 : 2, ip: '', // Empty Ip string is required, server gets the ip from HTTP header dnt: utils.getDNT() ? 1 : 0, } @@ -157,21 +106,16 @@ function RhythmOneBidAdapter() { sizeList = adUnit.mediaTypes.banner.sizes; } var sizeStringList = utils.parseSizesInput(sizeList); - if (!Array.isArray(sizeStringList)) { - return {}; - } - var format = []; sizeStringList.forEach(function(size) { - if (!size) { - return; - } - var dimensionList = getValidSizeSet(size.split('x')); - if (dimensionList) { - format.push({ - 'w': dimensionList[0], - 'h': dimensionList[1], - }); + if (size) { + var dimensionList = getValidSizeSet(size.split('x')); + if (dimensionList) { + format.push({ + 'w': dimensionList[0], + 'h': dimensionList[1], + }); + } } }); if (format.length) { @@ -179,7 +123,8 @@ function RhythmOneBidAdapter() { 'format': format }; } - return {}; + + return false; } function frameVideo(bid) { @@ -272,7 +217,9 @@ function RhythmOneBidAdapter() { rmpUrl += '&hbv=' + prebidVersion.replace(fat, '') + ',' + version.replace(fat, ''); var bidRequest = frameBid(BRs, bidderRequest); - loadStart = Date.now(); + if (!bidRequest.imp.length) { + return {}; + } return { method: 'POST', diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index e909827b2df..6b414db47ab 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -91,9 +91,7 @@ describe('rhythmone adapter tests', function () { }, 'mediaTypes': { 'video': { - 'playerSize': [ - [640, 480] - ], + 'playerSize': [640, 480], 'context': 'instream' } }, @@ -332,7 +330,7 @@ describe('rhythmone adapter tests', function () { expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(600); }); - it('survives size misconfiguration', function () { + it('does not return request for invalid banner size configuration', function () { var bidRequestList = [ { 'bidder': 'rhythmone', @@ -356,22 +354,20 @@ describe('rhythmone adapter tests', function () { ]; var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - - const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.imp[0].banner.format).to.be.undefined; + expect(bidRequest.method).to.be.undefined; }); - it('dnt is correctly set to 1', function () { + it('does not return request for missing banner size configuration', function () { var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' }, 'mediaTypes': { - 'banner': { - 'sizes': [[300, 600]] - } + 'banner': {} }, 'adUnitCode': 'div-gpt-ad-1438287399331-0', 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', @@ -382,23 +378,42 @@ describe('rhythmone adapter tests', function () { } ]; - var dntStub = sinon.stub(utils, 'getDNT').returns(1); - var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + expect(bidRequest.method).to.be.undefined; + }); - dntStub.restore(); + it('reject bad sizes', function () { + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaTypes': { + 'banner': {'sizes': [['400', '500'], ['4n0', '5g0']]} + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.device.dnt).to.equal(1); + expect(openrtbRequest.imp[0].banner.format.length).to.equal(1); }); - it('sets floor', function () { + it('dnt is correctly set to 1', function () { var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { 'placementId': 'myplacement', - 'floor': 100.0 }, 'mediaTypes': { 'banner': { @@ -414,26 +429,30 @@ describe('rhythmone adapter tests', function () { } ]; + var dntStub = sinon.stub(utils, 'getDNT').returns(1); + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + dntStub.restore(); + const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.imp[0].bidfloor).to.equal(100.0); + expect(openrtbRequest.device.dnt).to.equal(1); }); - it('support for correct video size definition', function () { + it('sets floor', function () { var bidRequestList = [ { 'bidder': 'rhythmone', 'params': { 'placementId': 'myplacement', + 'floor': 100.0 }, 'mediaTypes': { - 'video': { - 'playerSize': [640, 480], - 'context': 'instream' + 'banner': { + 'sizes': [[300, 600]] } }, - 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', 'bidderRequestId': '418b37f85e772c', 'auctionId': '18fd8b8b0bd757', @@ -445,8 +464,7 @@ describe('rhythmone adapter tests', function () { var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.imp[0].video.w).to.equal(640); - expect(openrtbRequest.imp[0].video.h).to.equal(480); + expect(openrtbRequest.imp[0].bidfloor).to.equal(100.0); }); it('supports string video sizes', function () { @@ -604,28 +622,6 @@ describe('rhythmone adapter tests', function () { }); }); - describe('auditBeacon', function() { - it('should contain the correct path', function() { - var syncList = r1adapter.getUserSyncs({pixelEnabled: true}); - expect(syncList.length).to.equal(1); - var syncData = syncList[0]; - var expectedURL = '//hbevents.1rx.io/audit?'; - assert.equal(syncData.url.substring(0, expectedURL.length), expectedURL); - }); - - it('should send GDPR Consent data to Sync pixel', function () { - var syncList = r1adapter.getUserSyncs({pixelEnabled: true}, null, {'gdprApplies': true, 'consentString': 'testConsentString'}); - expect(syncList.length).to.equal(1); - var syncData = syncList[0]; - expect(syncData.url).to.have.string('&gdpr=true&gdpr_consent=testConsentString'); - }); - - it('should not return anything when pixelEnabled is false', function () { - var syncList = r1adapter.getUserSyncs({pixelEnabled: false}, null, {'gdprApplies': true, 'consentString': 'testConsentString'}); - expect(syncList).to.be.undefined; - }); - }); - describe('isBidRequestValid', function () { var bid = { 'bidder': 'rhythmone', From 552d160e11584215c98afbaa7435505af5a7d8b7 Mon Sep 17 00:00:00 2001 From: my6sense Date: Mon, 22 Jul 2019 17:58:06 +0300 Subject: [PATCH 091/436] My6Sense: Endpoint subdomain changed. (#3982) * My6sense new adapter * endpoint fix * Code fix * Added changes in adapter md file * Changed the end point * supportedMediaTypes values added * md file was updated with a valid widget key * endpoint changed * indentation issues fixed --- modules/my6senseBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/my6senseBidAdapter.js b/modules/my6senseBidAdapter.js index 38aa1da8573..1f6080d82b9 100644 --- a/modules/my6senseBidAdapter.js +++ b/modules/my6senseBidAdapter.js @@ -2,7 +2,7 @@ import { BANNER, NATIVE } from '../src/mediaTypes'; const {registerBidder} = require('../src/adapters/bidderFactory'); const BIDDER_CODE = 'my6sense'; -const END_POINT = '//papi.mynativeplatform.com/pub2/web/v1.15.0/hbwidget.json'; +const END_POINT = '//hb.mynativeplatform.com/pub2/web/v1.15.0/hbwidget.json'; const END_POINT_METHOD = 'POST'; // called first From 9fe08372974c0bb8835fabcb4c37573f74940b25 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 22 Jul 2019 09:15:29 -0600 Subject: [PATCH 092/436] update user sync to allow for multiple auction syncs (#3984) --- src/userSync.js | 30 +++++++++++++++++++----------- test/spec/userSync_spec.js | 7 +++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/userSync.js b/src/userSync.js index 3cbdc58a075..2d5dfbd9a28 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -24,8 +24,8 @@ export function newUserSync(userSyncDependencies) { // Let getDefaultQueue() set the defaults let queue = getDefaultQueue(); - // Whether or not user syncs have been trigger on this page load - let hasFired = false; + // Whether or not user syncs have been trigger on this page load for a specific bidder + let hasFiredBidder = new Set(); // How many bids for each adapter let numAdapterBids = {}; @@ -33,7 +33,7 @@ export function newUserSync(userSyncDependencies) { let permittedPixels = { image: false, iframe: false - } + }; // Use what is in config by default let usConfig = userSyncDependencies.config; @@ -61,7 +61,7 @@ export function newUserSync(userSyncDependencies) { * @private */ function fireSyncs() { - if (!usConfig.syncEnabled || !userSyncDependencies.browserSupportsCookies || (!usConfig.enableOverride && hasFired)) { + if (!usConfig.syncEnabled || !userSyncDependencies.browserSupportsCookies) { return; } @@ -75,7 +75,16 @@ export function newUserSync(userSyncDependencies) { } // Reset the user sync queue queue = getDefaultQueue(); - hasFired = true; + } + + function forEachFire(queue, fn) { + // Randomize the order of the pixels before firing + // This is to avoid giving any bidder who has registered multiple syncs + // any preferential treatment and balancing them out + utils.shuffle(queue).forEach((sync) => { + fn(sync); + hasFiredBidder.add(sync[0]); + }); } /** @@ -87,10 +96,7 @@ export function newUserSync(userSyncDependencies) { if (!(usConfig.pixelEnabled || permittedPixels.image)) { return; } - // Randomize the order of the pixels before firing - // This is to avoid giving any bidder who has registered multiple syncs - // any preferential treatment and balancing them out - utils.shuffle(queue.image).forEach((sync) => { + forEachFire(queue.image, (sync) => { let [bidderName, trackingPixelUrl] = sync; utils.logMessage(`Invoking image pixel user sync for bidder: ${bidderName}`); // Create image object and add the src url @@ -107,8 +113,7 @@ export function newUserSync(userSyncDependencies) { if (!(usConfig.iframeEnabled || permittedPixels.iframe)) { return; } - // Randomize the order of these syncs just like the pixels above - utils.shuffle(queue.iframe).forEach((sync) => { + forEachFire(queue.iframe, (sync) => { let [bidderName, iframeUrl] = sync; utils.logMessage(`Invoking iframe user sync for bidder: ${bidderName}`); // Insert iframe into DOM @@ -146,6 +151,9 @@ export function newUserSync(userSyncDependencies) { * userSync.registerSync('image', 'rubicon', 'http://example.com/pixel') */ publicApi.registerSync = (type, bidder, url) => { + if (hasFiredBidder.has(bidder)) { + return utils.logWarn(`already registered syncs for "${bidder}"`); + } if (!usConfig.syncEnabled || !utils.isArray(queue[type])) { return utils.logWarn(`User sync type "${type}" not supported`); } diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index f330be4c2f4..f55fe13c528 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -98,15 +98,18 @@ describe('user sync', function () { expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should only trigger syncs once per page', function () { + it('should only trigger syncs once per page per bidder', function () { const userSync = newTestUserSync({pixelEnabled: true}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.syncUsers(); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); + userSync.registerSync('image', 'testBidder2', 'http://example.com/3'); userSync.syncUsers(); + expect(triggerPixelStub.callCount).to.equal(2); expect(triggerPixelStub.getCall(0)).to.not.be.null; expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); - expect(triggerPixelStub.getCall(1)).to.be.null; + expect(triggerPixelStub.getCall(1)).to.not.be.null; + expect(triggerPixelStub.getCall(1).args[0]).to.exist.and.to.equal('http://example.com/3'); }); it('should not fire syncs if cookies are not supported', function () { From 736adc41dd98f9c2f07c1c735284c014ce758312 Mon Sep 17 00:00:00 2001 From: yeeldpadsquad <52921150+yeeldpadsquad@users.noreply.github.com> Date: Mon, 22 Jul 2019 18:45:54 +0200 Subject: [PATCH 093/436] Padsquad bid adapter (#4002) * padsquad bid adapter * padsquad bid adapter * removed unnecessary log line --- modules/padsquadBidAdapter.js | 132 ++++++++++ modules/padsquadBidAdapter.md | 33 +++ test/spec/modules/padsquadBidAdapter_spec.js | 261 +++++++++++++++++++ 3 files changed, 426 insertions(+) create mode 100644 modules/padsquadBidAdapter.js create mode 100644 modules/padsquadBidAdapter.md create mode 100644 test/spec/modules/padsquadBidAdapter_spec.js diff --git a/modules/padsquadBidAdapter.js b/modules/padsquadBidAdapter.js new file mode 100644 index 00000000000..f5800bed7c9 --- /dev/null +++ b/modules/padsquadBidAdapter.js @@ -0,0 +1,132 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import * as utils from '../src/utils'; +import {BANNER} from '../src/mediaTypes'; + +const ENDPOINT_URL = '//x.padsquad.com/auction'; + +const DEFAULT_BID_TTL = 30; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_NET_REVENUE = true; + +export const spec = { + code: 'padsquad', + supportedMediaTypes: [BANNER], + + isBidRequestValid: function (bid) { + return (!!bid.params.unitId && typeof bid.params.unitId === 'string') || + (!!bid.params.networkId && typeof bid.params.networkId === 'string') || + (!!bid.params.publisherId && typeof bid.params.publisherId === 'string'); + }, + + buildRequests: function (validBidRequests, bidderRequest) { + if (!validBidRequests || !bidderRequest) { + return; + } + const publisherId = validBidRequests[0].params.publisherId; + const networkId = validBidRequests[0].params.networkId; + const impressions = validBidRequests.map(bidRequest => ({ + id: bidRequest.bidId, + banner: { + format: bidRequest.sizes.map(sizeArr => ({ + w: sizeArr[0], + h: sizeArr[1] + })) + }, + ext: { + exchange: { + unitId: bidRequest.params.unitId + } + } + })); + + const openrtbRequest = { + id: bidderRequest.auctionId, + imp: impressions, + site: { + domain: window.location.hostname, + page: window.location.href, + ref: bidderRequest.refererInfo ? bidderRequest.refererInfo.referer || null : null + }, + ext: { + exchange: { + publisherId: publisherId, + networkId: networkId, + } + } + }; + + // apply gdpr + if (bidderRequest.gdprConsent) { + openrtbRequest.regs = {ext: {gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0}}; + openrtbRequest.user = {ext: {consent: bidderRequest.gdprConsent.consentString}}; + } + + const payloadString = JSON.stringify(openrtbRequest); + return { + method: 'POST', + url: ENDPOINT_URL, + data: payloadString, + }; + }, + + interpretResponse: function (serverResponse, request) { + const bidResponses = []; + const response = (serverResponse || {}).body; + // response is always one seat with (optional) bids for each impression + if (response && response.seatbid && response.seatbid.length === 1 && response.seatbid[0].bid && response.seatbid[0].bid.length) { + response.seatbid[0].bid.forEach(bid => { + bidResponses.push({ + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + ad: bid.adm, + ttl: DEFAULT_BID_TTL, + creativeId: bid.crid, + netRevenue: DEFAULT_NET_REVENUE, + currency: DEFAULT_CURRENCY, + }) + }) + } else { + utils.logInfo('padsquad.interpretResponse :: no valid responses to interpret'); + } + return bidResponses; + }, + getUserSyncs: function (syncOptions, serverResponses) { + utils.logInfo('padsquad.getUserSyncs', 'syncOptions', syncOptions, 'serverResponses', serverResponses); + let syncs = []; + + if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { + return syncs; + } + + serverResponses.forEach(resp => { + const userSync = utils.deepAccess(resp, 'body.ext.usersync'); + if (userSync) { + let syncDetails = []; + Object.keys(userSync).forEach(key => { + const value = userSync[key]; + if (value.syncs && value.syncs.length) { + syncDetails = syncDetails.concat(value.syncs); + } + }); + syncDetails.forEach(syncDetails => { + syncs.push({ + type: syncDetails.type === 'iframe' ? 'iframe' : 'image', + url: syncDetails.url + }); + }); + + if (!syncOptions.iframeEnabled) { + syncs = syncs.filter(s => s.type !== 'iframe') + } + if (!syncOptions.pixelEnabled) { + syncs = syncs.filter(s => s.type !== 'image') + } + } + }); + return syncs; + }, + +}; +registerBidder(spec); diff --git a/modules/padsquadBidAdapter.md b/modules/padsquadBidAdapter.md new file mode 100644 index 00000000000..0a69db42ce3 --- /dev/null +++ b/modules/padsquadBidAdapter.md @@ -0,0 +1,33 @@ +# Overview + +``` +Module Name: Padsquad Bid Adapter +Module Type: Bidder Adapter +Maintainer: yeeldpadsquad@gmail.com +``` + +# Description + +Connects to Padsquad exchange for bids. + +Padsquad bid adapter supports Banner ads. + +# Test Parameters +``` +var adUnits = [ + { + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'padsquad', + params: { + unitId: 'test' + } + }] + } +]; +``` diff --git a/test/spec/modules/padsquadBidAdapter_spec.js b/test/spec/modules/padsquadBidAdapter_spec.js new file mode 100644 index 00000000000..aba1efea32f --- /dev/null +++ b/test/spec/modules/padsquadBidAdapter_spec.js @@ -0,0 +1,261 @@ +import {expect} from 'chai'; +import {spec} from 'modules/padsquadBidAdapter'; + +const REQUEST = { + 'bidderCode': 'padsquad', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708', + 'bidderRequestId': 'requestId', + 'bidRequest': [{ + 'bidder': 'padsquad', + 'params': { + 'unitId': 123456, + }, + 'placementCode': 'div-gpt-dummy-placement-code', + 'sizes': [ + [300, 250] + ], + 'bidId': 'bidId1', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708' + }, + { + 'bidder': 'padsquad', + 'params': { + 'unitId': 123456, + }, + 'placementCode': 'div-gpt-dummy-placement-code', + 'sizes': [ + [300, 250] + ], + 'bidId': 'bidId2', + 'bidderRequestId': 'bidderRequestId', + 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708' + }], + 'start': 1487883186070, + 'auctionStart': 1487883186069, + 'timeout': 3000 +}; + +const RESPONSE = { + 'headers': null, + 'body': { + 'id': 'responseId', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'bidId1', + 'impid': 'bidId1', + 'price': 0.18, + 'adm': '', + 'adid': '144762342', + 'adomain': [ + 'http://dummydomain.com' + ], + 'iurl': 'iurl', + 'cid': '109', + 'crid': 'creativeId', + 'cat': [], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 334553, + 'auction_id': 514667951122925701, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + }, + { + 'id': 'bidId2', + 'impid': 'bidId2', + 'price': 0.1, + 'adm': '', + 'adid': '144762342', + 'adomain': [ + 'http://dummydomain.com' + ], + 'iurl': 'iurl', + 'cid': '109', + 'crid': 'creativeId', + 'cat': [], + 'w': 300, + 'h': 250, + 'ext': { + 'prebid': { + 'type': 'banner' + }, + 'bidder': { + 'appnexus': { + 'brand_id': 386046, + 'auction_id': 517067951122925501, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + } + ], + 'seat': 'seat' + } + ], + 'ext': { + 'usersync': { + 'sovrn': { + 'status': 'none', + 'syncs': [ + { + 'url': 'urlsovrn', + 'type': 'iframe' + } + ] + }, + 'appnexus': { + 'status': 'none', + 'syncs': [ + { + 'url': 'urlappnexus', + 'type': 'pixel' + } + ] + } + }, + 'responsetimemillis': { + 'appnexus': 127 + } + } + } +}; + +describe('Padsquad bid adapter', function () { + describe('isBidRequestValid', function () { + it('should accept request if only unitId is passed', function () { + let bid = { + bidder: 'padsquad', + params: { + unitId: 'unitId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should accept request if only networkId is passed', function () { + let bid = { + bidder: 'padsquad', + params: { + networkId: 'networkId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should accept request if only publisherId is passed', function () { + let bid = { + bidder: 'padsquad', + params: { + publisherId: 'publisherId', + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('reject requests without params', function () { + let bid = { + bidder: 'padsquad', + params: {} + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + it('creates request data', function () { + let request = spec.buildRequests(REQUEST.bidRequest, REQUEST); + + expect(request).to.exist.and.to.be.a('object'); + const payload = JSON.parse(request.data); + expect(payload.imp[0]).to.have.property('id', REQUEST.bidRequest[0].bidId); + expect(payload.imp[1]).to.have.property('id', REQUEST.bidRequest[1].bidId); + }); + + it('has gdpr data if applicable', function () { + const req = Object.assign({}, REQUEST, { + gdprConsent: { + consentString: 'consentString', + gdprApplies: true, + } + }); + let request = spec.buildRequests(REQUEST.bidRequest, req); + + const payload = JSON.parse(request.data); + expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString); + expect(payload.regs.ext).to.have.property('gdpr', 1); + }); + }); + + describe('interpretResponse', function () { + it('have bids', function () { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + expect(bids).to.be.an('array').that.is.not.empty; + validateBidOnIndex(0); + validateBidOnIndex(1); + + function validateBidOnIndex(index) { + expect(bids[index]).to.have.property('currency', 'USD'); + expect(bids[index]).to.have.property('requestId', RESPONSE.body.seatbid[0].bid[index].impid); + expect(bids[index]).to.have.property('cpm', RESPONSE.body.seatbid[0].bid[index].price); + expect(bids[index]).to.have.property('width', RESPONSE.body.seatbid[0].bid[index].w); + expect(bids[index]).to.have.property('height', RESPONSE.body.seatbid[0].bid[index].h); + expect(bids[index]).to.have.property('ad', RESPONSE.body.seatbid[0].bid[index].adm); + expect(bids[index]).to.have.property('creativeId', RESPONSE.body.seatbid[0].bid[index].crid); + expect(bids[index]).to.have.property('ttl', 30); + expect(bids[index]).to.have.property('netRevenue', true); + } + }); + + it('handles empty response', function () { + const EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {}}); + const bids = spec.interpretResponse(EMPTY_RESP, REQUEST); + + expect(bids).to.be.empty; + }); + }); + + describe('getUserSyncs', function () { + it('handles no parameters', function () { + let opts = spec.getUserSyncs({}); + expect(opts).to.be.an('array').that.is.empty; + }); + it('returns non if sync is not allowed', function () { + let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}); + + expect(opts).to.be.an('array').that.is.empty; + }); + + it('iframe sync enabled should return results', function () { + let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [RESPONSE]); + + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('iframe'); + expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['sovrn'].syncs[0].url); + }); + + it('pixel sync enabled should return results', function () { + let opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [RESPONSE]); + + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('image'); + expect(opts[0].url).to.equal(RESPONSE.body.ext.usersync['appnexus'].syncs[0].url); + }); + + it('all sync enabled should return all results', function () { + let opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [RESPONSE]); + + expect(opts.length).to.equal(2); + }); + }); +}); From 40a4558071f32dbcb00c387991717e2c300d679a Mon Sep 17 00:00:00 2001 From: Sudhanshu patel Date: Tue, 23 Jul 2019 05:12:41 +0530 Subject: [PATCH 094/436] SRE-1994: s3 http domain migration (#4012) --- .../modules/adgenerationBidAdapter_spec.js | 22 +++++++++---------- test/spec/modules/kummaBidAdapter_spec.js | 8 +++---- .../spec/modules/platformioBidAdapter_spec.js | 8 +++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/spec/modules/adgenerationBidAdapter_spec.js b/test/spec/modules/adgenerationBidAdapter_spec.js index 28bccd7844e..2b8834f1e1d 100644 --- a/test/spec/modules/adgenerationBidAdapter_spec.js +++ b/test/spec/modules/adgenerationBidAdapter_spec.js @@ -199,7 +199,7 @@ describe('AdgenerationAdapter', function () { results: [], }, banner: { - ad: '
', + ad: '
', beacon: '', cpm: 36.0008, displaytype: '1', @@ -215,11 +215,11 @@ describe('AdgenerationAdapter', function () { dealid: 'fd5sa5fa7f', ttl: 1000, results: [ - {ad: '
'}, + {ad: '
'}, ] }, native: { - ad: '↵ ↵ ↵ ↵ ↵
↵ ', + ad: '↵ ↵ ↵ ↵ ↵
↵ ', beacon: '', cpm: 36.0008, displaytype: '1', @@ -261,7 +261,7 @@ describe('AdgenerationAdapter', function () { id: 2, img: { h: 250, - url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + url: 'https://sdk-temp.s3-ap-northeast-1.amazonaws.com/adg-sample-ad/img/300x250.png', w: 300 }, required: 1 @@ -291,10 +291,10 @@ describe('AdgenerationAdapter', function () { required: 0 } ], - imptrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'], + imptrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1.gif'], link: { clicktrackers: [ - 'https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif' + 'https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1_clicktracker_access.gif' ], url: 'https://supership.jp' }, @@ -322,7 +322,7 @@ describe('AdgenerationAdapter', function () { currency: 'JPY', netRevenue: true, ttl: 1000, - ad: '
', + ad: '
', }, native: { requestId: '2f6ac468a9c15e', @@ -334,11 +334,11 @@ describe('AdgenerationAdapter', function () { currency: 'JPY', netRevenue: true, ttl: 1000, - ad: '↵
', + ad: '↵
', native: { title: 'Title', image: { - url: 'https://s3-ap-northeast-1.amazonaws.com/sdk-temp/adg-sample-ad/img/300x250.png', + url: 'https://sdk-temp.s3-ap-northeast-1.amazonaws.com/adg-sample-ad/img/300x250.png', height: 250, width: 300 }, @@ -352,8 +352,8 @@ describe('AdgenerationAdapter', function () { cta: 'CTA', privacyLink: 'https://supership.jp/optout/#', clickUrl: 'https://supership.jp', - clickTrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1_clicktracker_access.gif'], - impressionTrackers: ['https://s3-ap-northeast-1.amazonaws.com/adg-dummy-dsp/1x1.gif'] + clickTrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1_clicktracker_access.gif'], + impressionTrackers: ['https://adg-dummy-dsp.s3-ap-northeast-1.amazonaws.com/1x1.gif'] }, mediaType: NATIVE } diff --git a/test/spec/modules/kummaBidAdapter_spec.js b/test/spec/modules/kummaBidAdapter_spec.js index 82076717dcc..7d33bd085b5 100644 --- a/test/spec/modules/kummaBidAdapter_spec.js +++ b/test/spec/modules/kummaBidAdapter_spec.js @@ -192,8 +192,8 @@ describe('Kumma Adapter Tests', function () { { id: 1, title: { text: 'Ad Title' } }, { id: 2, data: { value: 'Test description' } }, { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + { id: 4, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_image.png', w: 300, h: 300 } } ], link: { url: 'http://brand.com/' } } @@ -220,8 +220,8 @@ describe('Kumma Adapter Tests', function () { expect(nativeBid).to.not.equal(null); expect(nativeBid.title).to.equal('Ad Title'); expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.icon.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_image.png'); expect(nativeBid.image.width).to.equal(300); expect(nativeBid.image.height).to.equal(300); expect(nativeBid.icon.width).to.equal(100); diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index f3754654cf1..4ef2dc1bba0 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -192,8 +192,8 @@ describe('Platform.io Adapter Tests', function () { { id: 1, title: { text: 'Ad Title' } }, { id: 2, data: { value: 'Test description' } }, { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + { id: 4, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://adx1public.s3.amazonaws.com/creatives_image.png', w: 300, h: 300 } } ], link: { url: 'http://brand.com/' } } @@ -220,8 +220,8 @@ describe('Platform.io Adapter Tests', function () { expect(nativeBid).to.not.equal(null); expect(nativeBid.title).to.equal('Ad Title'); expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.icon.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://adx1public.s3.amazonaws.com/creatives_image.png'); expect(nativeBid.image.width).to.equal(300); expect(nativeBid.image.height).to.equal(300); expect(nativeBid.icon.width).to.equal(100); From 62b085c35be521306f53048fe244c21c9461e749 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Mon, 22 Jul 2019 20:28:42 -0400 Subject: [PATCH 095/436] Debug update and remove setConfig hook (#4007) * Debug update and remove setConfig hook * fix config failing on circular dependency with utils --- src/config.js | 10 ++++++---- src/utils.js | 8 -------- test/spec/debugging_spec.js | 1 + 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/config.js b/src/config.js index a1a8af629d8..7645da18d8f 100644 --- a/src/config.js +++ b/src/config.js @@ -10,10 +10,12 @@ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -import { hook } from './hook'; +import { parseQS } from './url'; + const utils = require('./utils'); +const CONSTANTS = require('./constants'); -const DEFAULT_DEBUG = false; +const DEFAULT_DEBUG = (parseQS(window.location.search)[CONSTANTS.DEBUG_MODE] || '').toUpperCase() === 'TRUE'; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_ENABLE_SEND_ALL_BIDS = true; @@ -231,7 +233,7 @@ export function newConfig() { * Sets configuration given an object containing key-value pairs and calls * listeners that were added by the `subscribe` function */ - let setConfig = hook('async', function setConfig(options) { + function setConfig(options) { if (typeof options !== 'object') { utils.logError('setConfig options must be an object'); return; @@ -251,7 +253,7 @@ export function newConfig() { }); callSubscribers(topicalConfig); - }); + } /** * Sets configuration defaults which setConfig values can be applied on top of diff --git a/src/utils.js b/src/utils.js index b5a46d174f4..09bb5435d56 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,8 +5,6 @@ import includes from 'core-js/library/fn/array/includes'; import { parse } from './url'; const CONSTANTS = require('./constants'); -var _loggingChecked = false; - var tArr = 'Array'; var tStr = 'String'; var tFn = 'Function'; @@ -354,12 +352,6 @@ export function hasConsoleLogger() { } export function debugTurnedOn() { - if (config.getConfig('debug') === false && _loggingChecked === false) { - const debug = getParameterByName(CONSTANTS.DEBUG_MODE).toUpperCase() === 'TRUE'; - config.setConfig({ debug }); - _loggingChecked = true; - } - return !!config.getConfig('debug'); } diff --git a/test/spec/debugging_spec.js b/test/spec/debugging_spec.js index d07f7fc3373..ba9702b0324 100644 --- a/test/spec/debugging_spec.js +++ b/test/spec/debugging_spec.js @@ -13,6 +13,7 @@ describe('bid overrides', function () { afterEach(function () { window.sessionStorage.clear(); + config.resetConfig(); sandbox.restore(); }); From ddae48c7934d3f7270d16e986ace2a4b84991ba7 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Mon, 22 Jul 2019 21:11:58 -0400 Subject: [PATCH 096/436] Rubicon integration type (#4008) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * Update Rubicon Bid and Analytics Adapters to read int_type from config * Unit tests for changes to Rubicon bid and analytics adapters --- modules/rubiconAnalyticsAdapter.js | 4 +-- modules/rubiconBidAdapter.js | 6 +++-- .../modules/rubiconAnalyticsAdapter_spec.js | 27 +++++++++++++++++++ test/spec/modules/rubiconBidAdapter_spec.js | 13 +++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index a00c727d470..e9e7daa59b3 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -28,7 +28,7 @@ config.getConfig('s2sConfig', ({s2sConfig}) => { }); export const SEND_TIMEOUT = 3000; -const INTEGRATION = 'pbjs'; +const DEFAULT_INTEGRATION = 'pbjs'; const cache = { auctions: {}, @@ -139,7 +139,7 @@ function sendMessage(auctionId, bidWonId) { let referrer = config.getConfig('pageUrl') || utils.getTopWindowUrl(); let message = { eventTimeMillis: Date.now(), - integration: INTEGRATION, + integration: config.getConfig('rubicon.int_type') || DEFAULT_INTEGRATION, version: '$prebid.version$', referrerUri: referrer }; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index b4b8e98e393..d8b101b6318 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; import {config} from '../src/config'; import {BANNER, VIDEO} from '../src/mediaTypes'; -const INTEGRATION = 'pbjs_lite_v$prebid.version$'; +const DEFAULT_INTEGRATION = 'pbjs_lite'; function isSecure() { return location.protocol === 'https:'; @@ -385,6 +385,8 @@ export const spec = { const [latitude, longitude] = params.latLong || []; + const configIntType = config.getConfig('rubicon.int_type'); + const data = { 'account_id': params.accountId, 'site_id': params.siteId, @@ -394,7 +396,7 @@ export const spec = { 'p_pos': params.position === 'atf' || params.position === 'btf' ? params.position : 'unknown', 'rp_floor': (params.floor = parseFloat(params.floor)) > 0.01 ? params.floor : 0.01, 'rp_secure': isSecure() ? '1' : '0', - 'tk_flint': INTEGRATION, + 'tk_flint': `${configIntType || DEFAULT_INTEGRATION}_v$prebid.version$`, 'x_source.tid': bidRequest.transactionId, 'p_screen_res': _getScreenResolution(), 'kw': Array.isArray(params.keywords) ? params.keywords.join(',') : '', diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index c6b0ca8d29f..5fb7fd7bf79 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -728,4 +728,31 @@ describe('rubicon analytics adapter', function () { expect(bidResponseObj.bidPriceUSD).to.equal(1.0); }); }); + + describe('config with integration type', () => { + it('should use the integration type provided in the config instead of the default', () => { + sandbox.stub(config, 'getConfig').callsFake(function (key) { + const config = { + 'rubicon.int_type': 'testType' + }; + return config[key]; + }); + + rubiconAnalyticsAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001 + } + }); + + performStandardAuction(); + + expect(requests.length).to.equal(1); + const request = requests[0]; + const message = JSON.parse(request.requestBody); + expect(message.integration).to.equal('testType'); + + rubiconAnalyticsAdapter.disableAnalytics(); + }); + }); }); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0ad20001536..988b518f348 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -2011,6 +2011,19 @@ describe('the rubicon adapter', function () { expect(bids[0].height).to.equal(480); }); }); + + describe('config with integration type', () => { + it('should use the integration type provided in the config instead of the default', () => { + sandbox.stub(config, 'getConfig').callsFake(function (key) { + const config = { + 'rubicon.int_type': 'testType' + }; + return config[key]; + }); + const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(parseQuery(request.data).tk_flint).to.equal('testType_v$prebid.version$'); + }); + }); }); }); From 7ba15a2476186bcf609e37aa0c510c0cc70bef4a Mon Sep 17 00:00:00 2001 From: Catalin Ciocov Date: Tue, 23 Jul 2019 17:39:41 +0300 Subject: [PATCH 097/436] Inskin Bid Adapter - New Feature (#4011) * Add support for different publisher payment models. * Add Inskin integration example. * Append pubcpm to impression tracker. * Added unit tests for pubCMP vs clearPrice. --- integrationExamples/gpt/inskin_example.html | 102 ++++++++++++++++++++ modules/inskinBidAdapter.js | 9 +- test/spec/modules/inskinBidAdapter_spec.js | 10 ++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 integrationExamples/gpt/inskin_example.html diff --git a/integrationExamples/gpt/inskin_example.html b/integrationExamples/gpt/inskin_example.html new file mode 100644 index 00000000000..197a5b1ffe1 --- /dev/null +++ b/integrationExamples/gpt/inskin_example.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + +

Prebid.js Test

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

Prebid.js Test

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

Basic Prebid.js Example

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

Prebid.js Test

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

Prebid.js Test

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

Prebid.js Test

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

Prebid.js Test

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

Prebid.js Test

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

Prebid.js Yieldbot Adapter Basic Example

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

Prebid Native

+
+

No response

+ +
+ +
+
+ +
+

No response

+ +
+ + + + diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 582b12e59d7..2ae32dd1df2 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -5,7 +5,8 @@ import { ajax } from '../../src/ajax'; import { STATUS, S2S, EVENTS } from '../../src/constants'; import adapterManager from '../../src/adapterManager'; import { config } from '../../src/config'; -import { VIDEO } from '../../src/mediaTypes'; +import { VIDEO, NATIVE } from '../../src/mediaTypes'; +import { processNativeAdUnitParams } from '../../src/native'; import { isValid } from '../../src/adapters/bidderFactory'; import events from '../../src/events'; import includes from 'core-js/library/fn/array/includes'; @@ -346,7 +347,7 @@ const LEGACY_PROTOCOL = { return request; }, - interpretResponse(result, bidderRequests, requestedBidders) { + interpretResponse(result, bidderRequests) { const bids = []; if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { @@ -431,11 +432,57 @@ const LEGACY_PROTOCOL = { } }; +// https://iabtechlab.com/wp-content/uploads/2016/07/OpenRTB-Native-Ads-Specification-Final-1.2.pdf#page=40 +let nativeDataIdMap = { + sponsoredBy: 1, // sponsored + body: 2, // desc + rating: 3, + likes: 4, + downloads: 5, + price: 6, + salePrice: 7, + phone: 8, + address: 9, + body2: 10, // desc2 + cta: 12 // ctatext +}; +let nativeDataNames = Object.keys(nativeDataIdMap); + +let nativeImgIdMap = { + icon: 1, + image: 3 +}; + +let nativeEventTrackerEventMap = { + impression: 1, + 'viewable-mrc50': 2, + 'viewable-mrc100': 3, + 'viewable-video50': 4, +}; + +let nativeEventTrackerMethodMap = { + img: 1, + js: 2 +}; + +// enable reverse lookup +[ + nativeDataIdMap, + nativeImgIdMap, + nativeEventTrackerEventMap, + nativeEventTrackerMethodMap +].forEach(map => { + Object.keys(map).forEach(key => { + map[map[key]] = key; + }); +}); + /* * Protocol spec for OpenRTB endpoint * e.g., https:///v1/openrtb2/auction */ let bidIdMap = {}; +let nativeAssetCache = {}; // store processed native params to preserve const OPEN_RTB_PROTOCOL = { buildRequest(s2sBidRequest, bidRequests, adUnits) { let imps = []; @@ -443,6 +490,74 @@ const OPEN_RTB_PROTOCOL = { // transform ad unit into array of OpenRTB impression objects adUnits.forEach(adUnit => { + const nativeParams = processNativeAdUnitParams(utils.deepAccess(adUnit, 'mediaTypes.native')); + let nativeAssets; + if (nativeParams) { + try { + nativeAssets = nativeAssetCache[adUnit.code] = Object.keys(nativeParams).reduce((assets, type) => { + let params = nativeParams[type]; + + function newAsset(obj) { + return Object.assign({ + required: params.required ? 1 : 0 + }, obj ? utils.cleanObj(obj) : {}); + } + + switch (type) { + case 'image': + case 'icon': + let imgTypeId = nativeImgIdMap[type]; + let asset = utils.cleanObj({ + type: imgTypeId, + w: utils.deepAccess(params, 'sizes.0'), + h: utils.deepAccess(params, 'sizes.1'), + wmin: utils.deepAccess(params, 'aspect_ratios.0.min_width') + }); + if (!(asset.w || asset.wmin)) { + throw 'invalid img sizes (must provided sizes or aspect_ratios)'; + } + if (Array.isArray(params.aspect_ratios)) { + // pass aspect_ratios as ext data I guess? + asset.ext = { + aspectratios: params.aspect_ratios.map( + ratio => `${ratio.ratio_width}:${ratio.ratio_height}` + ) + } + } + assets.push(newAsset({ + img: asset + })); + break; + case 'title': + if (!params.len) { + throw 'invalid title.len'; + } + assets.push(newAsset({ + title: { + len: params.len + } + })); + break; + default: + let dataAssetTypeId = nativeDataIdMap[type]; + if (dataAssetTypeId) { + assets.push(newAsset({ + data: { + type: dataAssetTypeId, + len: params.len + } + })) + } + } + return assets; + }, []); + } catch (e) { + utils.logError('error creating native request: ' + String(e)) + } + } + const videoParams = utils.deepAccess(adUnit, 'mediaTypes.video'); + const bannerParams = utils.deepAccess(adUnit, 'mediaTypes.banner'); + adUnit.bids.forEach(bid => { // OpenRTB response contains the adunit code and bidder name. These are // combined to create a unique key for each bid since an id isn't returned @@ -454,14 +569,13 @@ const OPEN_RTB_PROTOCOL = { } }); - let banner; + let mediaTypes = {}; // default to banner if mediaTypes isn't defined - if (utils.isEmpty(adUnit.mediaTypes)) { + if (!(nativeParams || videoParams || bannerParams)) { const sizeObjects = adUnit.sizes.map(size => ({ w: size[0], h: size[1] })); - banner = {format: sizeObjects}; + mediaTypes['banner'] = {format: sizeObjects}; } - const bannerParams = utils.deepAccess(adUnit, 'mediaTypes.banner'); if (bannerParams && bannerParams.sizes) { const sizes = utils.parseSizesInput(bannerParams.sizes); @@ -473,13 +587,37 @@ const OPEN_RTB_PROTOCOL = { return { w, h }; }); - banner = {format}; + mediaTypes['banner'] = {format}; } - let video; - const videoParams = utils.deepAccess(adUnit, 'mediaTypes.video'); if (!utils.isEmpty(videoParams)) { - video = videoParams; + if (videoParams.context === 'outstream' && !adUnit.renderer) { + // Don't push oustream w/o renderer to request object. + utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); + } else { + mediaTypes['video'] = videoParams; + } + } + + if (nativeAssets) { + try { + mediaTypes['native'] = { + request: JSON.stringify({ + // TODO: determine best way to pass these and if we allow defaults + context: 1, + plcmttype: 1, + eventtrackers: [ + {event: 1, methods: [1]} + ], + // TODO: figure out how to support privacy field + // privacy: int + assets: nativeAssets + }), + ver: '1.2' + } + } catch (e) { + utils.logError('error creating native request: ' + String(e)) + } } // get bidder params in form { : {...params} } @@ -494,16 +632,11 @@ const OPEN_RTB_PROTOCOL = { const imp = { id: adUnit.code, ext, secure: _s2sConfig.secure }; - if (banner) { imp.banner = banner; } - if (video) { - if (video.context === 'outstream' && !adUnit.renderer) { - // Don't push oustream w/o renderer to request object. - utils.logError('Outstream bid without renderer cannot be sent to Prebid Server.'); - } else { - imp.video = video; - } + Object.assign(imp, mediaTypes); + + if (imp.banner || imp.video || imp.native) { + imps.push(imp); } - if (imp.banner || imp.video) { imps.push(imp); } }); if (!imps.length) { @@ -609,7 +742,7 @@ const OPEN_RTB_PROTOCOL = { return request; }, - interpretResponse(response, bidderRequests, requestedBidders) { + interpretResponse(response, bidderRequests) { const bids = []; if (response.seatbid) { @@ -665,6 +798,60 @@ const OPEN_RTB_PROTOCOL = { if (bid.adm) { bidObject.vastXml = bid.adm; } if (!bidObject.vastUrl && bid.nurl) { bidObject.vastUrl = bid.nurl; } + } else if (utils.deepAccess(bid, 'ext.prebid.type') === NATIVE) { + bidObject.mediaType = NATIVE; + let adm; + if (typeof bid.adm === 'string') { + adm = bidObject.adm = JSON.parse(bid.adm); + } else { + adm = bidObject.adm = bid.adm; + } + + let trackers = { + [nativeEventTrackerMethodMap.img]: adm.imptrackers || [], + [nativeEventTrackerMethodMap.js]: adm.jstracker ? [adm.jstracker] : [] + }; + if (adm.eventtrackers) { + adm.eventtrackers.forEach(tracker => { + switch (tracker.method) { + case nativeEventTrackerMethodMap.img: + trackers[nativeEventTrackerMethodMap.img].push(tracker.url); + break; + case nativeEventTrackerMethodMap.js: + trackers[nativeEventTrackerMethodMap.js].push(tracker.url); + break; + } + }); + } + + if (utils.isPlainObject(adm) && Array.isArray(adm.assets)) { + let origAssets = nativeAssetCache[bidRequest.adUnitCode]; + bidObject.native = utils.cleanObj(adm.assets.reduce((native, asset) => { + let origAsset = origAssets[asset.id]; + if (utils.isPlainObject(asset.img)) { + native[origAsset.img.type ? nativeImgIdMap[origAsset.img.type] : 'image'] = utils.pick( + asset.img, + ['url', 'w as width', 'h as height'] + ); + } else if (utils.isPlainObject(asset.title)) { + native['title'] = asset.title.text + } else if (utils.isPlainObject(asset.data)) { + nativeDataNames.forEach(dataType => { + if (nativeDataIdMap[dataType] === origAsset.data.type) { + native[dataType] = asset.data.value; + } + }); + } + return native; + }, utils.cleanObj({ + clickUrl: adm.link, + clickTrackers: utils.deepAccess(adm, 'link.clicktrackers'), + impressionTrackers: trackers[nativeEventTrackerMethodMap.img], + javascriptTrackers: trackers[nativeEventTrackerMethodMap.js] + }))); + } else { + utils.logError('prebid server native response contained no assets'); + } } else { // banner if (bid.adm && bid.nurl) { bidObject.ad = bid.adm; @@ -732,10 +919,13 @@ export function PrebidServer() { const adUnits = utils.deepClone(s2sBidRequest.ad_units); // at this point ad units should have a size array either directly or mapped so filter for that - const adUnitsWithSizes = adUnits.filter(unit => unit.sizes && unit.sizes.length); + const validAdUnits = adUnits.filter(unit => + (unit.sizes && unit.sizes.length) || + (unit.mediaTypes && unit.mediaTypes.native) + ); // in case config.bidders contains invalid bidders, we only process those we sent requests for - const requestedBidders = adUnitsWithSizes + const requestedBidders = validAdUnits .map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)) .reduce(utils.flatten) .filter(utils.uniques); @@ -745,7 +935,7 @@ export function PrebidServer() { queueSync(_s2sConfig.bidders, consent); } - const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, adUnitsWithSizes); + const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, validAdUnits); const requestJson = request && JSON.stringify(request); if (request && requestJson) { ajax( diff --git a/modules/rubiconAnalyticsAdapter.js b/modules/rubiconAnalyticsAdapter.js index b165741b49d..560cab91dca 100644 --- a/modules/rubiconAnalyticsAdapter.js +++ b/modules/rubiconAnalyticsAdapter.js @@ -36,33 +36,6 @@ const cache = { timeouts: {}, }; -// basically lodash#pick that also allows transformation functions and property renaming -function _pick(obj, properties) { - return properties.reduce((newObj, prop, i) => { - if (typeof prop === 'function') { - return newObj; - } - - let newProp = prop; - let match = prop.match(/^(.+?)\sas\s(.+?)$/i); - - if (match) { - prop = match[1]; - newProp = match[2]; - } - - let value = obj[prop]; - if (typeof properties[i + 1] === 'function') { - value = properties[i + 1](value, newObj); - } - if (typeof value !== 'undefined') { - newObj[newProp] = value; - } - - return newObj; - }, {}); -} - function stringProperties(obj) { return Object.keys(obj).reduce((newObj, prop) => { let value = obj[prop]; @@ -98,7 +71,7 @@ function formatSource(src) { function sendMessage(auctionId, bidWonId) { function formatBid(bid) { - return _pick(bid, [ + return utils.pick(bid, [ 'bidder', 'bidId', 'status', @@ -113,7 +86,7 @@ function sendMessage(auctionId, bidWonId) { 'clientLatencyMillis', 'serverLatencyMillis', 'params', - 'bidResponse', bidResponse => bidResponse ? _pick(bidResponse, [ + 'bidResponse', bidResponse => bidResponse ? utils.pick(bidResponse, [ 'bidPriceUSD', 'dealId', 'dimensions', @@ -122,7 +95,7 @@ function sendMessage(auctionId, bidWonId) { ]); } function formatBidWon(bid) { - return Object.assign(formatBid(bid), _pick(bid.adUnit, [ + return Object.assign(formatBid(bid), utils.pick(bid.adUnit, [ 'adUnitCode', 'transactionId', 'videoAdFormat', () => bid.videoAdFormat, @@ -153,7 +126,7 @@ function sendMessage(auctionId, bidWonId) { let bid = auctionCache.bids[bidId]; let adUnit = adUnits[bid.adUnit.adUnitCode]; if (!adUnit) { - adUnit = adUnits[bid.adUnit.adUnitCode] = _pick(bid.adUnit, [ + adUnit = adUnits[bid.adUnit.adUnitCode] = utils.pick(bid.adUnit, [ 'adUnitCode', 'transactionId', 'mediaTypes', @@ -191,7 +164,7 @@ function sendMessage(auctionId, bidWonId) { // This allows the bidWon events to have these params even in the case of a delayed render Object.keys(auctionCache.bids).forEach(function (bidId) { let adCode = auctionCache.bids[bidId].adUnit.adUnitCode; - Object.assign(auctionCache.bids[bidId], _pick(adUnitMap[adCode], ['accountId', 'siteId', 'zoneId'])); + Object.assign(auctionCache.bids[bidId], utils.pick(adUnitMap[adCode], ['accountId', 'siteId', 'zoneId'])); }); let auction = { @@ -237,7 +210,7 @@ function sendMessage(auctionId, bidWonId) { } export function parseBidResponse(bid) { - return _pick(bid, [ + return utils.pick(bid, [ 'bidPriceUSD', () => { if (typeof bid.currency === 'string' && bid.currency.toUpperCase() === 'USD') { return Number(bid.cpm); @@ -251,7 +224,7 @@ export function parseBidResponse(bid) { 'dealId', 'status', 'mediaType', - 'dimensions', () => _pick(bid, [ + 'dimensions', () => utils.pick(bid, [ 'width', 'height' ]) @@ -327,7 +300,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { case AUCTION_INIT: // set the rubicon aliases setRubiconAliases(adapterManager.aliasRegistry); - let cacheEntry = _pick(args, [ + let cacheEntry = utils.pick(args, [ 'timestamp', 'timeout' ]); @@ -340,7 +313,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { // mark adUnits we expect bidWon events for cache.auctions[args.auctionId].bidsWon[bid.adUnitCode] = false; - memo[bid.bidId] = _pick(bid, [ + memo[bid.bidId] = utils.pick(bid, [ 'bidder', bidder => bidder.toLowerCase(), 'bidId', 'status', () => 'no-bid', // default a bid to no-bid until response is recieved or bid is timed out @@ -349,7 +322,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { switch (bid.bidder) { // specify bidder params we want here case 'rubicon': - return _pick(params, [ + return utils.pick(params, [ 'accountId', 'siteId', 'zoneId' @@ -380,7 +353,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, { } } }, - 'adUnit', () => _pick(bid, [ + 'adUnit', () => utils.pick(bid, [ 'adUnitCode', 'transactionId', 'sizes as dimensions', sizes => sizes.map(sizeToDimensions), diff --git a/src/utils.js b/src/utils.js index a43151f89e4..6f592a8bcfe 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1137,6 +1137,53 @@ export function convertCamelToUnderscore(value) { return value.replace(/(?:^|\.?)([A-Z])/g, function (x, y) { return '_' + y.toLowerCase() }).replace(/^_/, ''); } +/** + * Returns a new object with undefined properties removed from given object + * @param obj the object to clean + */ +export function cleanObj(obj) { + return Object.keys(obj).reduce((newObj, key) => { + if (typeof obj[key] !== 'undefined') { + newObj[key] = obj[key]; + } + return newObj; + }, {}) +} + +/** + * Create a new object with selected properties. Also allows property renaming and transform functions. + * @param obj the original object + * @param properties An array of desired properties + */ +export function pick(obj, properties) { + if (typeof obj !== 'object') { + return {}; + } + return properties.reduce((newObj, prop, i) => { + if (typeof prop === 'function') { + return newObj; + } + + let newProp = prop; + let match = prop.match(/^(.+?)\sas\s(.+?)$/i); + + if (match) { + prop = match[1]; + newProp = match[2]; + } + + let value = obj[prop]; + if (typeof properties[i + 1] === 'function') { + value = properties[i + 1](value, newObj); + } + if (typeof value !== 'undefined') { + newObj[newProp] = value; + } + + return newObj; + }, {}); +} + /** * Converts an object of arrays (either strings or numbers) into an array of objects containing key and value properties * normally read from bidder params diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 8b077ca796a..0542385c5d5 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -33,6 +33,19 @@ const REQUEST = { 'mediaTypes': { 'banner': { 'sizes': [[ 300, 250 ], [ 300, 300 ]] + }, + 'native': { + 'title': { + 'required': true, + 'len': 800 + }, + 'image': { + 'required': true, + 'sizes': [989, 742], + }, + 'sponsoredBy': { + 'required': true + } } }, 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', @@ -382,6 +395,93 @@ const RESPONSE_OPENRTB_VIDEO = { }, }; +const RESPONSE_OPENRTB_NATIVE = { + 'id': 'c7dcf14f', + 'seatbid': [ + { + 'bid': [ + { + 'id': '6451317310275562039', + 'impid': 'div-gpt-ad-1460505748561-0', + 'price': 10, + 'adm': { + 'ver': '1.2', + 'assets': [ + { + 'id': 1, + 'img': { + 'url': 'https://vcdn.adnxs.com/p/creative-image/f8/7f/0f/13/f87f0f13-230c-4f05-8087-db9216e393de.jpg', + 'w': 989, + 'h': 742, + 'ext': { + 'appnexus': { + 'prevent_crop': 0 + } + } + } + }, + { + 'id': 0, + 'title': { + 'text': 'This is a Prebid Native Creative' + } + }, + { + 'id': 2, + 'data': { + 'value': 'Prebid.org' + } + } + ], + 'link': { + 'url': 'https://lax1-ib.adnxs.com/click?AAAAAAAAJEAAAAAAAAAkQAAAAAAAACRAAAAAAAAAJEAAAAAAAAAkQGdce2vBWudAJZpFu1er1zA7ZzddAAAAAOLoyQBtJAAAbSQAAAIAAAC8pM8FnPgWAAAAAABVU0QAVVNEAAEAAQBNXQAAAAABAgMCAAAAALsAuhVqdgAAAAA./cpcpm=AAAAAAAAAAA=/bcr=AAAAAAAA8D8=/pp=${AUCTION_PRICE}/cnd=%213Q5HCQj8-LwKELzJvi4YnPFbIAQoADEAAAAAAAAkQDoJTEFYMTo0MDc3QKcPSQAAAAAAAPA_UQAAAAAAAAAAWQAAAAAAAAAAYQAAAAAAAAAAaQAAAAAAAAAAcQAAAAAAAAAA/cca=OTMyNSNMQVgxOjQwNzc=/bn=84305/test=1/clickenc=http%3A%2F%2Fprebid.org%2Fdev-docs%2Fshow-native-ads.html' + }, + 'eventtrackers': [ + { + 'event': 1, + 'method': 1, + 'url': 'https://lax1-ib.adnxs.com/it?an_audit=0&test=1&referrer=http%3A%2F%2Flocalhost%3A9999%2FintegrationExamples%2Fgpt%2Fdemo_native.html&e=wqT_3QKCCKACBAAAAwDWAAUBCLvO3ekFEOe47duW2NbzQBiltJba--rq6zAqNgkAAAECCCRAEQEHEAAAJEAZEQkAIREJACkRCQAxEQmoMOLRpwY47UhA7UhIAlC8yb4uWJzxW2AAaM26dXjRkgWAAQGKAQNVU0SSAQEG8FKYAQGgAQGoAQGwAQC4AQLAAQPIAQLQAQnYAQDgAQHwAQCKAjt1ZignYScsIDI1Mjk4ODUsIDE1NjM5MTE5OTUpO3VmKCdyJywgOTc0OTQyMDQsIC4eAPQ0AZICnQIhb2pkaWlnajgtTHdLRUx6SnZpNFlBQ0NjOFZzd0FEZ0FRQVJJN1VoUTR0R25CbGdBWVAwQmFBQndBSGdBZ0FFQWlBRUFrQUVCbUFFQm9BRUJxQUVEc0FFQXVRSHpyV3FrQUFBa1FNRUI4NjFxcEFBQUpFREpBVVZpYmxDaFpRQkEyUUVBQUFBQUFBRHdQLUFCQVBVQkFBQUFBUGdCQUpnQ0FLQUNBTFVDQUFBQUFMMENBQUFBQU1BQ0FNZ0NBT0FDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEX1BpOENyb0RDVXhCV0RFNk5EQTNOLUFEcHctUUJBQ1lCQUhCQkFBQUFBQUFBQUFBeVFRQUFBQUFBQUFBQU5nRUFBLi6aAoUBITNRNUhDUWo4LUx3S0VMeiUhJG5QRmJJQVFvQUQRvVhBa1FEb0pURUZZTVRvME1EYzNRS2NQUxFUDFBBX1URDAxBQUFXHQwAWR0MAGEdDABjHQz0FwHYAgDgAq2YSOoCPmh0dHA6Ly9sb2NhbGhvc3Q6OTk5OS9pbnRlZ3JhdGlvbkV4YW1wbGVzL2dwdC9kZW1vX25hdGl2ZS5odG1sgAMAiAMBkAMAmAMUoAMBqgMAwAPgqAHIAwDYAwDgAwDoAwD4AwOABACSBAkvb3BlbnJ0YjKYBACiBA0xNzMuMjQ0LjM2LjQwqATtoySyBAwIABAAGAAgADAAOAC4BADABADIBADSBA45MzI1I0xBWDE6NDA3N9oEAggB4AQA8AS8yb4uiAUBmAUAoAX___________8BqgUkZTU5YzNlYjYtNmRkNi00MmQ5LWExMWEtM2FhMTFjOTc5MGUwwAUAyQUAAAAAAADwP9IFCQkAaVh0ANgFAeAFAfAFmfQh-gUECAAQAJAGAZgGALgGAMEGCSQk8D_IBgDaBhYKEAkQGQEBwTTgBgzyBgIIAIAHAYgHAA..&s=11ababa390e9f7983de260493fc5b91ec5b1b3d4&pp=${AUCTION_PRICE}' + } + ] + }, + 'adid': '97494204', + 'adomain': [ + 'http://prebid.org' + ], + 'iurl': 'https://lax1-ib.adnxs.com/cr?id=97494204', + 'cid': '9325', + 'crid': '97494204', + 'cat': [ + 'IAB3-1' + ], + 'ext': { + 'prebid': { + 'targeting': { + 'hb_bidder': 'appnexus', + 'hb_pb': '10.00' + }, + 'type': 'native', + 'video': { + 'duration': 0, + 'primary_category': '' + } + }, + 'bidder': { + 'appnexus': { + 'brand_id': 555545, + 'auction_id': 4676806524825984103, + 'bidder_id': 2, + 'bid_ad_type': 3 + } + } + } + } + ], + 'seat': 'appnexus' + } + ] +}; + const RESPONSE_UNSUPPORTED_BIDDER = { 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', 'status': 'OK', @@ -641,7 +741,7 @@ describe('S2S Adapter', function () { }); }); - it('adds device and app objects to request for ORTB', function () { + it('adds device and app objects to request for OpenRTB', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -689,6 +789,54 @@ describe('S2S Adapter', function () { }); }); + it('adds native request for OpenRTB', function () { + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + }); + + const _config = { + s2sConfig: s2sConfig + }; + + config.setConfig(_config); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid = JSON.parse(requests[0].requestBody); + + expect(requestBid.imp[0].native).to.deep.equal({ + request: JSON.stringify({ + 'context': 1, + 'plcmttype': 1, + 'eventtrackers': [{ + event: 1, + methods: [1] + }], + 'assets': [ + { + 'required': 1, + 'title': { + 'len': 800 + } + }, + { + 'required': 1, + 'img': { + 'type': 3, + 'w': 989, + 'h': 742 + } + }, + { + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + }), + ver: '1.2' + }); + }); + it('adds site if app is not present', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' @@ -1404,6 +1552,33 @@ describe('S2S Adapter', function () { expect(response).to.have.property('vastUrl', 'https://prebid-cache.net/cache?uuid=a5ad3993'); }); + it('handles OpenRTB native responses', function () { + sinon.stub(utils, 'getBidRequest').returns({ + adUnitCode: 'div-gpt-ad-1460505748561-0', + bidder: 'appnexus', + bidId: '123' + }); + const s2sConfig = Object.assign({}, CONFIG, { + endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' + }); + config.setConfig({s2sConfig}); + + server.respondWith(JSON.stringify(RESPONSE_OPENRTB_NATIVE)); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + server.respond(); + + sinon.assert.calledOnce(addBidResponse); + const response = addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('adm').deep.equal(RESPONSE_OPENRTB_NATIVE.seatbid[0].bid[0].adm); + expect(response).to.have.property('mediaType', 'native'); + expect(response).to.have.property('bidderCode', 'appnexus'); + expect(response).to.have.property('requestId', '123'); + expect(response).to.have.property('cpm', 10); + + utils.getBidRequest.restore(); + }); + it('should log warning for unsupported bidder', function () { server.respondWith(JSON.stringify(RESPONSE_UNSUPPORTED_BIDDER)); From 4ba91020769cd93ad60d4e71cd68f226a6004d6f Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Tue, 30 Jul 2019 20:04:43 +0300 Subject: [PATCH 122/436] MarsMedia adapter: Update prebid api (#3978) * Create Mars bid adapter * Fix ESLint errors * Add more tab between 86-97 for ESLint --- modules/marsmediaBidAdapter.js | 130 ++++++++++++++++++ modules/marsmediaBidAdapter.md | 32 +++++ test/spec/modules/marsmediaBidAdapter_spec.js | 122 ++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 modules/marsmediaBidAdapter.js create mode 100644 modules/marsmediaBidAdapter.md create mode 100644 test/spec/modules/marsmediaBidAdapter_spec.js diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js new file mode 100644 index 00000000000..09eb4ac6c75 --- /dev/null +++ b/modules/marsmediaBidAdapter.js @@ -0,0 +1,130 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +const BIDDER_CODE = 'marsmedia'; + +function getDomain() { + if (!utils.inIframe()) { + return window.location.hostname + } + let origins = window.document.location.ancestorOrigins + if (origins && origins.length > 0) { + return origins[origins.length - 1] + } +} + +export const spec = { + code: BIDDER_CODE, + aliases: ['mars'], + isBidRequestValid: function(bid) { + return (bid.params.publisherID !== null); + }, + buildRequests: function(validBidRequests, bidderRequest) { + try { + let protocol = (window.location.protocol === 'https:'); + const parse = getSize(validBidRequests[0].sizes); + const publisherId = validBidRequests[0].params.publisherID; + const payload = { + id: validBidRequests[0].bidId, + cur: ['USD'], + + language: window.navigator.userLanguage || window.navigator.language, + site: { + id: publisherId, + domain: getDomain(), + page: document.URL, + ref: document.referrer, + publisher: { + id: publisherId, + domain: getDomain() + } + }, + imp: [{ + id: utils.getUniqueIdentifierStr(), + banner: { + w: parse.width, + h: parse.height, + secure: protocol + }, + bidfloor: parseFloat(validBidRequests[0].params.floor) > 0 ? validBidRequests[0].params.floor : 0 + }], + device: { + ua: navigator.userAgent + }, + user: { + id: publisherId + }, + publisher: { + id: publisherId, + domain: getDomain() + } + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr = { + applies: bidderRequest.gdprConsent.gdprApplies, + consent: bidderRequest.gdprConsent.consentString + }; + } + + return { + method: 'POST', + url: '//bid306.rtbsrv.com/bidder/?bid=3mhdom', + data: JSON.stringify(payload) + }; + } catch (e) { + utils.logError(e, {validBidRequests, bidderRequest}); + } + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + let res = serverResponse.body; + if (!res) { + return [] + } + + for (let x = 0; x < res.seatbid.length; x++) { + var bidAd = res.seatbid[x].bid[0]; + + bidResponses.push({ + requestId: res.id, + cpm: Number(bidAd.price), + width: bidAd.w, + height: bidAd.h, + ad: bidAd.adm, + ttl: 60, + creativeId: bidAd.cid, + netRevenue: true, + currency: 'USD' + }) + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + return []; + } +}; + +function getSize(requestSizes) { + const parsed = {}; + const size = utils.parseSizesInput(requestSizes)[0]; + + if (typeof size !== 'string') { + return parsed; + } + + const parsedSize = size.toUpperCase().split('X'); + const width = parseInt(parsedSize[0], 10); + if (width) { + parsed.width = width; + } + + const height = parseInt(parsedSize[1], 10); + if (height) { + parsed.height = height; + } + + return parsed; +} + +registerBidder(spec); diff --git a/modules/marsmediaBidAdapter.md b/modules/marsmediaBidAdapter.md new file mode 100644 index 00000000000..fee962f9173 --- /dev/null +++ b/modules/marsmediaBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +``` +Module Name: Mars Media Group (mars.media) Bidder Adapter +Module Type: Bidder Adapter +Maintainer: vladi@mars.media +``` + +# Description + +Prebid adapter for Mars Media Group RTB. Requires approval and account setup. + +# Test Parameters + +## Web +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "marsmedia", + params: { + publisherID: 9999, + floor: 0.11 + } + } + ] + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js new file mode 100644 index 00000000000..a58857e0f3f --- /dev/null +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -0,0 +1,122 @@ +import { expect } from 'chai' +import { spec, _getPlatform } from 'modules/marsmediaBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +describe('marsmediaBidAdapter', function () { + const adapter = newBidder(spec) + + let bidRequest = { + 'bidId': '123', + 'sizes': [[ 300, 250 ]], + 'params': { + 'publisherID': 9999, + 'floor': 0.1 + } + } + + describe('codes', function () { + it('should return a bidder code of marsmedia', function () { + expect(spec.code).to.equal('marsmedia') + }) + it('should alias mars', function () { + expect(spec.aliases.length > 0 && spec.aliases[0] === 'mars').to.be.true + }) + }) + + describe('isBidRequestValid', function () { + it('should return true if all params present', function () { + expect(spec.isBidRequestValid(bidRequest)).to.be.true + }) + + it('should return false if any parameter missing', function () { + expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { publisherID: null } }))).to.be.false + }) + }) + + describe('buildRequests', function () { + let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) + let rdata + + it('should return request object', function () { + expect(req).to.not.be.null + }) + + it('should build request data', function () { + expect(req.data).to.not.be.null + }) + + it('should include one request', function () { + rdata = JSON.parse(req.data) + expect(rdata.imp.length).to.equal(1) + }) + + it('should include all publisher params', function () { + let r = rdata.imp[0] + expect(r.publisherID !== null).to.be.true + }) + }) + + describe('interpretResponse', function () { + let response; + beforeEach(function () { + response = { + body: { + 'id': '37386aade21a71', + 'seatbid': [{ + 'bid': [{ + 'id': '1', + 'impid': '1', + 'cid': '1', + 'price': 0.1, + 'nurl': '', + 'adm': '', + 'w': 320, + 'h': 250 + }] + }] + } + }; + }); + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '37386aade21a71', + 'cpm': 0.1, + 'width': 320, + 'height': 250, + 'creativeId': '1', + 'currency': 'USD', + 'netRevenue': true, + 'ad': ``, + 'ttl': 60 + }]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('handles empty bid response', function () { + let response = { + body: '' + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', function () { + /* it('should return iframe sync', function () { + let sync = spec.getUserSyncs({ iframeEnabled: true }) + expect(sync.length).to.equal(1) + expect(sync[0].type === 'iframe') + expect(typeof sync[0].url === 'string') + }) + + it('should return pixel sync', function () { + let sync = spec.getUserSyncs({ pixelEnabled: true }) + expect(sync.length).to.equal(1) + expect(sync[0].type === 'image') + expect(typeof sync[0].url === 'string') + }) */ + }) +}) From 9e9ca01bb488b39c9047992e9dd16fcd045f81e2 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 30 Jul 2019 15:29:38 -0400 Subject: [PATCH 123/436] Appnexus native view tracker (#4022) * First pass: adding viewability script to rtbBid * Added viewability scrit in the right place * Clean up * Corrected script position, added a workaround to get the adId after the bid's creation and fixed tests * Removed debugging logs * More cleanup * Opted to append rtbBid.viewability.config to the existing (nativeAd.javascript_trackers) in the bidAdapter's newBid function * Removed AnalyticsAdaper code and added bidAdapter.onBidWon to check for our jstracker and update their src attributes. * Added a way to differentiate scripts and clean up * Changed newBid to disarm jstracker before it's ready and changed onBidWon to arm it. This prevents the tracker from being loaded twice. * Making the code more robust * Grouped code in a function. Also changed parameters to reflect that finding the element will now fall be a view_js responsability. * Changed parameter pbjs_iframeid name to pbjs_auc so its not misleading * Variable name change to better reflect its nature * Fixing URL parameters (; separated and replacing completely the useless one) * undo changes to appnexus Analytics adapter * update regex variable * update regex again --- modules/appnexusBidAdapter.js | 116 ++++++++++++++++++- src/native.js | 1 - test/spec/modules/appnexusBidAdapter_spec.js | 12 +- test/spec/unit/pbjs_api_spec.js | 12 +- 4 files changed, 134 insertions(+), 7 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 67388848815..d0f4774185e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -33,6 +33,9 @@ const NATIVE_MAPPING = { const SOURCE = 'pbjs'; const MAX_IMPS_PER_REQUEST = 15; const mappingFileUrl = '//acdn.adnxs.com/prebid/appnexus-mapping/mappings.json'; +const SCRIPT_TAG_START = '= 1; + + let regexMatchFileName = str.match(VIEWABILITY_FILE_NAME); + let fileNameInStr = regexMatchFileName != null && regexMatchFileName.length >= 1; + + return str.startsWith(SCRIPT_TAG_START) && fileNameInStr && viewUrlStartInStr; +} + +function getAppnexusViewabilityScriptFromJsTrackers(jsTrackerArray) { + let viewJsPayload; + if (utils.isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) { + viewJsPayload = jsTrackerArray; + } else if (utils.isArray(jsTrackerArray)) { + for (let i = 0; i < jsTrackerArray.length; i++) { + let currentJsTracker = jsTrackerArray[i]; + if (strIsAppnexusViewabilityScript(currentJsTracker)) { + viewJsPayload = currentJsTracker; + } + } + } + return viewJsPayload; +} + +function getViewabilityScriptUrlFromPayload(viewJsPayload) { + // extracting the content of the src attribute + // -> substring between src=" and " + let indexOfFirstQuote = viewJsPayload.indexOf('src="') + 5; // offset of 5: the length of 'src=' + 1 + let indexOfSecondQuote = viewJsPayload.indexOf('"', indexOfFirstQuote); + let jsTrackerSrc = viewJsPayload.substring(indexOfFirstQuote, indexOfSecondQuote); + return jsTrackerSrc; +} + function formatRequest(payload, bidderRequest) { let request = []; @@ -415,6 +513,22 @@ function newBid(serverBid, rtbBid, bidderRequest) { } } else if (rtbBid.rtb[NATIVE]) { const nativeAd = rtbBid.rtb[NATIVE]; + + // setting up the jsTracker: + // we put it as a data-src attribute so that the tracker isn't called + // until we have the adId (see onBidWon) + let jsTrackerDisarmed = rtbBid.viewability.config.replace('src=', 'data-src='); + + let jsTrackers = nativeAd.javascript_trackers; + + if (jsTrackers == undefined) { + jsTrackers = jsTrackerDisarmed; + } else if (utils.isStr(jsTrackers)) { + jsTrackers = [jsTrackers, jsTrackerDisarmed]; + } else { + jsTrackers.push(jsTrackerDisarmed); + } + bid[NATIVE] = { title: nativeAd.title, body: nativeAd.desc, @@ -433,7 +547,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { displayUrl: nativeAd.displayurl, clickTrackers: nativeAd.link.click_trackers, impressionTrackers: nativeAd.impression_trackers, - javascriptTrackers: nativeAd.javascript_trackers + javascriptTrackers: jsTrackers }; if (nativeAd.main_img) { bid['native'].image = { diff --git a/src/native.js b/src/native.js index c9a67ca7541..6252eb133b3 100644 --- a/src/native.js +++ b/src/native.js @@ -132,7 +132,6 @@ export function nativeBidIsValid(bid, bidRequests) { */ export function fireNativeTrackers(message, adObject) { let trackers; - if (message.action === 'click') { trackers = adObject['native'] && adObject['native'].clickTrackers; } else { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 30d2dc08159..e1cca8c05ff 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -665,6 +665,9 @@ describe('AppNexusAdapter', function () { 'cpm_publisher_currency': 0.5, 'publisher_currency_code': '$', 'client_initiated_ad_counting': true, + 'viewability': { + 'config': '' + }, 'rtb': { 'banner': { 'content': '', @@ -744,7 +747,8 @@ describe('AppNexusAdapter', function () { 'video': { 'content': '' } - } + }, + 'javascriptTrackers': '' }] }] }; @@ -775,6 +779,9 @@ describe('AppNexusAdapter', function () { 'content': '', 'duration_ms': 30000, } + }, + 'viewability': { + 'config': '' } }] }] @@ -831,7 +838,8 @@ describe('AppNexusAdapter', function () { 'saleprice': 'FREE', 'phone': '1234567890', 'address': '28 W 23rd St, New York, NY 10010', - 'privacy_link': 'http://appnexus.com/?url=privacy_url' + 'privacy_link': 'http://appnexus.com/?url=privacy_url', + 'javascriptTrackers': '' }; let bidderRequest = { bids: [{ diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index d4daec0c266..c73604cac82 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -434,7 +434,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; @@ -574,7 +576,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; @@ -606,7 +610,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; From e556e90d2f6469249f4c507adaa2f4a0c0169696 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 30 Jul 2019 15:43:45 -0400 Subject: [PATCH 124/436] Prebid 2.26.0 release --- package-lock.json | 805 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 398 insertions(+), 409 deletions(-) diff --git a/package-lock.json b/package-lock.json index 56cac603a79..0c84e4db70d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,49 +1,49 @@ { "name": "prebid.js", - "version": "2.23.0-pre", + "version": "2.26.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", "dev": true, "requires": { "@babel/highlight": "^7.0.0" } }, "@babel/core": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", - "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helpers": "^7.4.4", - "@babel/parser": "^7.4.5", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.5", - "@babel/types": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", "dev": true, "requires": { - "@babel/types": "^7.4.4", + "@babel/types": "^7.5.5", "jsesc": "^2.5.1", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -79,14 +79,14 @@ } }, "@babel/helper-define-map": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" } }, "@babel/helper-explode-assignable-expression": { @@ -129,12 +129,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.5.5" } }, "@babel/helper-module-imports": { @@ -147,17 +147,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", "@babel/template": "^7.4.4", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" } }, "@babel/helper-optimise-call-expression": { @@ -176,12 +176,12 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.13" } }, "@babel/helper-remap-async-to-generator": { @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-member-expression-to-functions": "^7.5.5", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" } }, "@babel/helper-simple-access": { @@ -241,20 +241,20 @@ } }, "@babel/helpers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", "dev": true, "requires": { "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" } }, "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -279,6 +279,16 @@ "@babel/plugin-syntax-async-generators": "^7.2.0" } }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } + }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", @@ -290,9 +300,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", + "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -329,6 +339,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", @@ -366,9 +385,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -386,27 +405,27 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", + "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.11" + "lodash": "^4.17.13" } }, "@babel/plugin-transform-classes": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.4", + "@babel/helper-define-map": "^7.5.5", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", + "@babel/helper-replace-supers": "^7.5.5", "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" } @@ -421,9 +440,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", + "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -441,9 +460,9 @@ } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -497,34 +516,37 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", + "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-umd": { @@ -556,13 +578,13 @@ } }, "@babel/plugin-transform-object-super": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" + "@babel/helper-replace-supers": "^7.5.5" } }, "@babel/plugin-transform-parameters": { @@ -662,43 +684,45 @@ } }, "@babel/preset-env": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", - "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", + "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.4", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.4", + "@babel/plugin-transform-async-to-generator": "^7.5.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.4.4", + "@babel/plugin-transform-block-scoping": "^7.5.5", + "@babel/plugin-transform-classes": "^7.5.5", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.4", + "@babel/plugin-transform-destructuring": "^7.5.0", "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.5.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", "@babel/plugin-transform-for-of": "^7.4.4", "@babel/plugin-transform-function-name": "^7.4.4", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-modules-systemjs": "^7.4.4", + "@babel/plugin-transform-modules-amd": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-modules-systemjs": "^7.5.0", "@babel/plugin-transform-modules-umd": "^7.2.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-object-super": "^7.5.5", "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/plugin-transform-regenerator": "^7.4.5", @@ -709,7 +733,7 @@ "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.4.4", + "@babel/types": "^7.5.5", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -729,30 +753,30 @@ } }, "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.11" + "lodash": "^4.17.13" } }, "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } }, @@ -829,14 +853,6 @@ "dev": true, "requires": { "samsam": "1.3.0" - }, - "dependencies": { - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - } } }, "@sinonjs/samsam": { @@ -923,9 +939,9 @@ } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, "after": { @@ -1093,12 +1109,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } } } @@ -1762,6 +1778,15 @@ "babel-runtime": "^6.22.0" } }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -2701,15 +2726,15 @@ } }, "bfj": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", - "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "check-types": "^7.3.0", - "hoopy": "^0.1.2", - "tryer": "^1.0.0" + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" } }, "big.js": { @@ -2816,6 +2841,12 @@ "toidentifier": "1.0.0" } }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2988,14 +3019,14 @@ } }, "browserslist": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", - "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", + "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000975", - "electron-to-chromium": "^1.3.164", - "node-releases": "^1.1.23" + "caniuse-lite": "^1.0.30000984", + "electron-to-chromium": "^1.3.191", + "node-releases": "^1.1.25" } }, "browserstack": { @@ -3008,30 +3039,15 @@ } }, "browserstack-local": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", - "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", + "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", "is-running": "^2.0.0", "ps-tree": "=1.1.1", - "sinon": "^1.17.6", "temp-fs": "^0.9.9" - }, - "dependencies": { - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" - } - } } }, "buffer": { @@ -3165,7 +3181,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3231,9 +3247,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000975", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", - "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", + "version": "1.0.30000987", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000987.tgz", + "integrity": "sha512-O3VrjtRMTxoU5Cn5/QSmXeIR1gkVps4j9jqfIm4FLaQ5JzqBlVjMUG1xWnoYFv8N+H3Lp++aa05TekyIbjHL7g==", "dev": true }, "caseless": { @@ -3320,9 +3336,9 @@ "dev": true }, "check-types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", - "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", + "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", "dev": true }, "chokidar": { @@ -3774,9 +3790,9 @@ }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -3794,13 +3810,13 @@ "dev": true }, "coveralls": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", - "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", + "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", "dev": true, "requires": { "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", + "js-yaml": "^3.13.1", "lcov-parse": "^0.0.10", "log-driver": "^1.2.7", "minimist": "^1.2.0", @@ -4729,15 +4745,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.164", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", - "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", + "version": "1.3.205", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.205.tgz", + "integrity": "sha512-VV+f2FVeFI5D/slUD7A3V1lTMDkQTUGWYH2dZGAijIutN5Aga4Fn/Hv4Gc+60OpXFVLYIq5HpXb2cG6NrGGQaA==", "dev": true }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4779,7 +4795,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4793,7 +4809,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4809,7 +4825,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4835,7 +4851,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -5212,9 +5228,9 @@ } }, "eslint-module-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", - "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5291,9 +5307,9 @@ } }, "eslint-plugin-import": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", - "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -5303,8 +5319,8 @@ "eslint-import-resolver-node": "^0.3.2", "eslint-module-utils": "^2.4.0", "has": "^1.0.3", - "lodash": "^4.17.11", "minimatch": "^3.0.4", + "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", "resolve": "^1.11.0" }, @@ -5446,6 +5462,10 @@ } } }, + "eslint-plugin-prebid": { + "version": "file:plugins/eslint", + "dev": true + }, "eslint-plugin-promise": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", @@ -5538,7 +5558,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5778,13 +5798,13 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", + "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -6196,9 +6216,9 @@ } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "flush-write-stream": { @@ -6275,15 +6295,6 @@ "mime-types": "^2.1.12" } }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "~1.1" - } - }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -6921,9 +6932,9 @@ } }, "fun-hooks": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", - "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", + "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" }, "function-bind": { "version": "1.1.1", @@ -7221,9 +7232,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", + "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", "dev": true }, "grapheme-splitter": { @@ -7672,7 +7683,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7689,7 +7700,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -7790,22 +7801,22 @@ "dev": true }, "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", "dev": true, "requires": { - "lodash._reinterpolate": "~3.0.0", + "lodash._reinterpolate": "^3.0.0", "lodash.templatesettings": "^4.0.0" } }, "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "requires": { - "lodash._reinterpolate": "~3.0.0" + "lodash._reinterpolate": "^3.0.0" } } } @@ -7867,9 +7878,9 @@ } }, "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", + "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", "dev": true, "requires": { "minimatch": "^3.0.3" @@ -8146,9 +8157,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -8416,7 +8427,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8424,6 +8435,14 @@ "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "http-parser-js": { @@ -8461,12 +8480,12 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", + "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, "requires": { - "agent-base": "^4.1.0", + "agent-base": "^4.3.0", "debug": "^3.1.0" }, "dependencies": { @@ -8540,9 +8559,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { @@ -8679,12 +8698,6 @@ "is-decimal": "^1.0.0" } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8811,12 +8824,6 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "dev": true - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -9125,12 +9132,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } } } @@ -9409,7 +9416,7 @@ "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha1-OJDKlyKxDR0UtybhM1kxRVeISZ4=", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -9629,12 +9636,12 @@ }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } } } @@ -9800,9 +9807,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "lodash._basecopy": { @@ -10040,7 +10047,7 @@ "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha1-5srO2Uln7uuc45n5+GgqSysoyP8=", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -10053,7 +10060,7 @@ "circular-json": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha1-kydjroj0996teg0JyKUaR0OlOx0=", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "debug": { @@ -10078,9 +10085,9 @@ } }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", "dev": true }, "longest": { @@ -10639,14 +10646,14 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -10675,7 +10682,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -11033,22 +11040,13 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } } } }, "node-releases": { - "version": "1.1.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", - "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", + "version": "1.1.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", + "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11234,18 +11232,6 @@ "isobject": "^3.0.0" } }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11306,6 +11292,18 @@ "make-iterator": "^1.0.0" } }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -11368,7 +11366,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11567,9 +11565,9 @@ } }, "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -12035,9 +12033,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "progress": { @@ -12090,9 +12088,9 @@ "dev": true }, "psl": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", - "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", + "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==", "dev": true }, "public-encrypt": { @@ -12388,9 +12386,9 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", - "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", "dev": true, "requires": { "private": "^0.1.6" @@ -12416,9 +12414,9 @@ } }, "regexp-tree": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", - "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", + "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", "dev": true }, "regexpp": { @@ -12716,6 +12714,14 @@ "requires": { "caller-path": "^0.1.0", "resolve-from": "^1.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } } }, "requires-port": { @@ -12725,9 +12731,9 @@ "dev": true }, "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12744,9 +12750,9 @@ } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "resolve-options": { @@ -12878,9 +12884,9 @@ "dev": true }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, "schema-utils": { @@ -13019,13 +13025,13 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", + "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -13073,9 +13079,9 @@ "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -13181,12 +13187,6 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true - }, - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true } } }, @@ -13330,7 +13330,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -13344,7 +13344,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13367,7 +13367,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13395,7 +13395,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13411,7 +13411,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13429,7 +13429,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13537,14 +13537,14 @@ } }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13678,7 +13678,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13940,9 +13940,9 @@ } }, "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", + "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", "dev": true, "requires": { "duplexify": "^3.5.0", @@ -14434,38 +14434,15 @@ } }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "unique-stream": { @@ -14679,7 +14656,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14687,16 +14664,20 @@ } }, "util": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", - "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, "requires": { - "inherits": "2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "object.entries": "^1.1.0", - "safe-buffer": "^5.1.2" + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "util-deprecate": { @@ -15088,9 +15069,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -15100,18 +15081,18 @@ } }, "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } }, "camelcase": { @@ -15404,9 +15385,9 @@ } }, "webpack-bundle-analyzer": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", - "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", + "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -15418,16 +15399,16 @@ "express": "^4.16.3", "filesize": "^3.6.1", "gzip-size": "^5.0.0", - "lodash": "^4.17.10", + "lodash": "^4.17.15", "mkdirp": "^0.5.1", "opener": "^1.5.1", "ws": "^6.0.0" }, "dependencies": { "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "dev": true }, "ejs": { @@ -15476,7 +15457,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15990,6 +15971,14 @@ "dev": true, "requires": { "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "vinyl": { @@ -16204,9 +16193,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { diff --git a/package.json b/package.json index 9d2bb82f25c..39c720953e2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.26.0-pre", + "version": "2.26.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 407160bee20e0f2e2e3a03f251a1aa0ceff1e3a3 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 30 Jul 2019 16:12:05 -0400 Subject: [PATCH 125/436] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c84e4db70d..06746ab8c41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.26.0", + "version": "2.27.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 39c720953e2..cb921f61bed 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.26.0", + "version": "2.27.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 75e247f51268d118cef4f9e51570596eca2ab143 Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Tue, 30 Jul 2019 23:52:46 +0300 Subject: [PATCH 126/436] Fix referrer encoding in The Media Grid Bid Adapter (#4040) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter * Update The Grid Media Bidder Adapter to send refererInfo.referer as 'u' parameter in ad request * Hotfix for referrer in Grid Bid Adapter --- modules/gridBidAdapter.js | 2 +- test/spec/modules/gridBidAdapter_spec.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index ee1ae85e7ee..2deaebf0635 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -86,7 +86,7 @@ export const spec = { if (bidderRequest) { if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + payload.u = bidderRequest.refererInfo.referer; } if (bidderRequest.timeout) { payload.wtimeout = bidderRequest.timeout; diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index d9bfb9e971a..a191d2211f5 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -48,7 +48,7 @@ describe('TheMediaGrid Adapter', function () { return res; } const bidderRequest = {refererInfo: {referer: 'http://example.com'}}; - const encodedReferer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; let bidRequests = [ { 'bidder': 'grid', @@ -89,7 +89,7 @@ describe('TheMediaGrid Adapter', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('auids', '1'); expect(payload).to.have.property('sizes', '300x250,300x600'); expect(payload).to.have.property('r', '22edbae2733bf6'); @@ -99,7 +99,7 @@ describe('TheMediaGrid Adapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('auids', '1,1,2'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); @@ -109,7 +109,7 @@ describe('TheMediaGrid Adapter', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}, refererInfo: bidderRequest.refererInfo}); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); - expect(payload).to.have.property('u', encodedReferer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('gdpr_consent', 'AAA'); expect(payload).to.have.property('gdpr_applies', '1'); }); From ff9f9ff1b4c085886145edcc3c4d2d60e4cefb7a Mon Sep 17 00:00:00 2001 From: Gaudeamus Date: Wed, 31 Jul 2019 07:56:52 +0300 Subject: [PATCH 127/436] [mgid] add referrer and utc offset to bid request (#4023) * make placementId optional * get referrer * fix formatting * fix formatting --- modules/mgidBidAdapter.js | 64 ++++++++++++++-------- test/spec/modules/mgidBidAdapter_spec.js | 68 +++++++++++++++++++----- 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index c3f88106893..154c00f6a06 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -60,7 +60,7 @@ utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] utils._each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset }); export const spec = { - VERSION: '1.3', + VERSION: '1.4', code: BIDDER_CODE, supportedMediaTypes: [BANNER, NATIVE], reId: /^[1-9][0-9]*$/, @@ -118,8 +118,9 @@ export const spec = { if (validBidRequests.length === 0) { return; } - const referer = utils.deepAccess(bidderRequest, 'refererInfo.referer'); - const hostname = urlUtils.parse(referer).hostname; + const info = pageInfo(); + const page = info.location || utils.deepAccess(bidderRequest, 'refererInfo.referer') || utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl'); + const hostname = urlUtils.parse(page).hostname; let domain = extractDomainFromHost(hostname) || hostname; const accountId = setOnAny(validBidRequests, 'params.accountId'); const muid = getLocalStorageSafely('mgMuidn'); @@ -127,8 +128,7 @@ export const spec = { if (utils.isStr(muid) && muid.length > 0) { url += '?muid=' + muid; } - const cur = [config.getConfig('currency.adServerCurrency') || setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || DEFAULT_CUR]; - const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || referer; + const cur = [setOnAny(validBidRequests, 'params.currency') || setOnAny(validBidRequests, 'params.cur') || config.getConfig('currency.adServerCurrency') || DEFAULT_CUR]; const secure = window.location.protocol === 'https:' ? 1 : 0; let imp = []; validBidRequests.forEach(bid => { @@ -166,22 +166,11 @@ export const spec = { return; } - let ext = {mgid_ver: spec.VERSION, prebid_ver: $$PREBID_GLOBAL$$.version}; - let user = {}; - let regs = {}; - if (bidderRequest && bidderRequest.gdprConsent) { - user.ext = { - consent: bidderRequest.gdprConsent.consentString - }; - - regs.ext = { - gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) - }; - } let request = { id: utils.deepAccess(bidderRequest, 'bidderRequestId'), - site: { domain, page }, + site: {domain, page}, cur: cur, + geo: {utcoffset: info.timeOffset}, device: { ua: navigator.userAgent, js: 1, @@ -190,11 +179,16 @@ export const spec = { w: screen.width, language: getLanguage() }, - user, - regs, - ext, + ext: {mgid_ver: spec.VERSION, prebid_ver: $$PREBID_GLOBAL$$.version}, imp }; + if (bidderRequest && bidderRequest.gdprConsent) { + request.user = {ext: {consent: bidderRequest.gdprConsent.consentString}}; + request.regs = {ext: {gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)}} + } + if (info.referrer) { + request.site.ref = info.referrer + } utils.logInfo(LOG_INFO_PREFIX + `buildRequest:`, request); return { method: 'POST', @@ -376,11 +370,14 @@ function createBannerRequest(bid) { } } } - return { + let r = { w: sizes && sizes[0][0], h: sizes && sizes[0][1], - format, + }; + if (format.length) { + r.format = format } + return r } function createNativeRequest(params) { @@ -558,3 +555,24 @@ function parseNativeResponse(bid, newBid) { } } } + +function pageInfo() { + var w, d, l, r, m, p, t; + for (w = window, d = w.document, l = d.location.href, r = d.referrer, m = 0, t = new Date(); w !== w.parent;) { + try { + p = w.parent; l = p.location.href; r = p.document.referrer; w = p; + } catch (e) { + m = top !== w.parent ? 2 : 1; + break + } + } + return { + location: l, + referrer: r || '', + masked: m, + wWidth: w.innerWidth, + wHeight: w.innerHeight, + date: t.toUTCString(), + timeOffset: t.getTimezoneOffset() + }; +} diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 2216122da18..4a9f25a29a7 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -30,6 +30,7 @@ describe('Mgid bid adapter', function () { const secure = window.location.protocol === 'https:' ? 1 : 0; const mgid_ver = spec.VERSION; const prebid_ver = $$PREBID_GLOBAL$$.version; + const utcOffset = (new Date()).getTimezoneOffset().toString(); describe('isBidRequestValid', function () { let bid = { @@ -359,13 +360,14 @@ describe('Mgid bid adapter', function () { } }; let bidRequests = [bid]; - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(page).hostname; const request = spec.buildRequests(bidRequests); expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); const data = JSON.parse(request.data); expect(data.site.domain).to.deep.equal(domain); + expect(data.site.page).to.deep.equal(page); expect(data.cur).to.deep.equal(['USD']); expect(data.device.ua).to.deep.equal(ua); expect(data.device.dnt).equal(dnt); @@ -373,12 +375,12 @@ describe('Mgid bid adapter', function () { expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250, format: []}); + expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250}); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250,\"format\":[]}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\",\"page\":\"' + page + '\"},\"cur\":[\"USD\"],\"geo\":{\"utcoffset\":' + utcOffset + '},\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":250}}]}', }); }); it('should not return native imp if minimum asset list not requested', function () { @@ -406,14 +408,15 @@ describe('Mgid bid adapter', function () { }; let bidRequests = [bid]; - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(page).hostname; const request = spec.buildRequests(bidRequests); expect(request).to.be.a('object'); expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); const data = JSON.parse(request.data); expect(data.site.domain).to.deep.equal(domain); + expect(data.site.page).to.deep.equal(page); expect(data.cur).to.deep.equal(['USD']); expect(data.device.ua).to.deep.equal(ua); expect(data.device.dnt).equal(dnt); @@ -426,7 +429,44 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":11,\"required\":0,\"data\":{\"type\":1}}]}}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\",\"page\":\"' + page + '\"},\"cur\":[\"USD\"],\"geo\":{\"utcoffset\":' + utcOffset + '},\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":11,\"required\":0,\"data\":{\"type\":1}}]}}}]}', + }); + }); + it('should return proper native imp', function () { + let bid = Object.assign({}, abid); + bid.mediaTypes = { + native: '', + }; + bid.nativeParams = { + title: {required: true}, + image: {wmin: 50, hmin: 50, required: true}, + icon: {}, + sponsored: { }, + }; + + let bidRequests = [bid]; + const page = top.location.href; + const domain = urlUtils.parse(page).hostname; + const request = spec.buildRequests(bidRequests); + expect(request).to.be.a('object'); + expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); + expect(request.method).deep.equal('POST'); + const data = JSON.parse(request.data); + expect(data.site.domain).to.deep.equal(domain); + expect(data.site.page).to.deep.equal(page); + expect(data.cur).to.deep.equal(['USD']); + expect(data.device.ua).to.deep.equal(ua); + expect(data.device.dnt).equal(dnt); + expect(data.device.h).equal(screenHeight); + expect(data.device.w).equal(screenWidth); + expect(data.device.language).to.deep.equal(lang); + expect(data.imp[0].tagid).to.deep.equal('2/div'); + expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 328, hmin: 50, 'type': 3, 'w': 492, wmin: 50}, 'required': 1}, {'id': 3, 'img': {'h': 50, 'type': 1, 'w': 50}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}}); + expect(data.imp[0].secure).to.deep.equal(secure); + expect(request).to.deep.equal({ + 'method': 'POST', + 'url': 'https://prebid.mgid.com/prebid/1', + 'data': '{\"site\":{\"domain\":\"' + domain + '\",\"page\":\"' + page + '\"},\"cur\":[\"USD\"],\"geo\":{\"utcoffset\":' + utcOffset + '},\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"w\":492,\"h\":328,\"wmin\":50,\"hmin\":50}},{\"id\":3,\"required\":0,\"img\":{\"type\":1,\"w\":50,\"h\":50}},{\"id\":11,\"required\":0,\"data\":{\"type\":1}}]}}}]}', }); }); it('should return proper native imp with sponsoredBy', function () { @@ -441,14 +481,15 @@ describe('Mgid bid adapter', function () { }; let bidRequests = [bid]; - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(page).hostname; const request = spec.buildRequests(bidRequests); expect(request).to.be.a('object'); expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); const data = JSON.parse(request.data); expect(data.site.domain).to.deep.equal(domain); + expect(data.site.page).to.deep.equal(page); expect(data.cur).to.deep.equal(['USD']); expect(data.device.ua).to.deep.equal(ua); expect(data.device.dnt).equal(dnt); @@ -461,7 +502,7 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\",\"page\":\"' + page + '\"},\"cur\":[\"USD\"],\"geo\":{\"utcoffset\":' + utcOffset + '},\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"native\":{\"request\":{\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}},{\"id\":2,\"required\":0,\"img\":{\"type\":3,\"w\":80,\"h\":80}},{\"id\":4,\"required\":0,\"data\":{\"type\":1}}]}}}]}', }); }); it('should return proper banner request', function () { @@ -474,12 +515,13 @@ describe('Mgid bid adapter', function () { let bidRequests = [bid]; const request = spec.buildRequests(bidRequests); - const referer = utils.deepAccess(bidRequests, 'refererInfo.referer'); - const domain = urlUtils.parse(referer).hostname; + const page = top.location.href; + const domain = urlUtils.parse(page).hostname; expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); const data = JSON.parse(request.data); expect(data.site.domain).to.deep.equal(domain); + expect(data.site.page).to.deep.equal(page); expect(data.cur).to.deep.equal(['USD']); expect(data.device.ua).to.deep.equal(ua); expect(data.device.dnt).equal(dnt); @@ -493,7 +535,7 @@ describe('Mgid bid adapter', function () { expect(request).to.deep.equal({ 'method': 'POST', 'url': 'https://prebid.mgid.com/prebid/1', - 'data': '{\"site\":{\"domain\":\"' + domain + '\"},\"cur\":[\"USD\"],\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"user\":{},\"regs\":{},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', + 'data': '{\"site\":{\"domain\":\"' + domain + '\",\"page\":\"' + page + '\"},\"cur\":[\"USD\"],\"geo\":{\"utcoffset\":' + utcOffset + '},\"device\":{\"ua\":\"' + ua + '\",\"js\":1,\"dnt\":' + dnt + ',\"h\":' + screenHeight + ',\"w\":' + screenWidth + ',\"language\":\"' + lang + '\"},\"ext\":{\"mgid_ver\":\"' + mgid_ver + '\",\"prebid_ver\":\"' + prebid_ver + '\"},\"imp\":[{\"tagid\":\"2/div\",\"secure\":' + secure + ',\"banner\":{\"w\":300,\"h\":600,\"format\":[{\"w\":300,\"h\":600},{\"w\":300,\"h\":250}]}}]}', }); }); }); From 5aca920ea172682a3e921a13ec5466c29c40016c Mon Sep 17 00:00:00 2001 From: ucfunnel <39581136+ucfunnel@users.noreply.github.com> Date: Wed, 31 Jul 2019 13:01:00 +0800 Subject: [PATCH 128/436] ucfunnel support tdid (#3977) * ucfunnel tdid support --- modules/ucfunnelBidAdapter.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index c1ac951066d..7974f053bbd 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -168,7 +168,7 @@ function getRequestData(bid, bidderRequest) { const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - + const userIdTdid = (bid.userId && bid.userId.tdid) ? bid.userId.tdid : ''; // general bid data let bidData = { ver: VER, @@ -181,7 +181,8 @@ function getRequestData(bid, bidderRequest) { ru: ref, adid: utils.getBidIdParameter('adid', bid.params), w: size[0], - h: size[1] + h: size[1], + tdid: userIdTdid }; if (bid.mediaType === 'video' || videoMediaType) { From 457924763d01fbce147807a7337531e72a889c21 Mon Sep 17 00:00:00 2001 From: mafernandez80 <50341807+mafernandez80@users.noreply.github.com> Date: Wed, 31 Jul 2019 02:08:24 -0300 Subject: [PATCH 129/436] Reload Adapter & Spec: Added GDPR and multiple sizes (#3967) * Reload Adapter & Spec: Added GDPR and multiple sizes * Reload Adapter - Fixed LGTM alert * Reload Adapter - Fixed import (path relative) * Reload Adapter: Read values from refererInfo and utils class. * Reload Adapter - Added onBidWon * Reload Adapter - Changed attribute's name * Reload Adapter - Backward Compatibility * Reload Adapter - Backward compatibility --- modules/reloadBidAdapter.js | 183 +++++++++++---------- test/spec/modules/reloadBidAdapter_spec.js | 6 +- 2 files changed, 96 insertions(+), 93 deletions(-) diff --git a/modules/reloadBidAdapter.js b/modules/reloadBidAdapter.js index a5f5ba43c60..4ecd4ff3390 100644 --- a/modules/reloadBidAdapter.js +++ b/modules/reloadBidAdapter.js @@ -1,18 +1,13 @@ -import { - BANNER -} - from '../src/mediaTypes'; import { registerBidder } from '../src/adapters/bidderFactory'; - +import * as utils from '../src/utils'; const BIDDER_CODE = 'reload'; - -const VERSION_ADAPTER = '1.0'; - +const VERSION_ADAPTER = '1.10'; export const spec = { code: BIDDER_CODE, + png: {}, /** * Determines whether or not the given bid request is valid. * @@ -31,31 +26,31 @@ export const spec = { */ buildRequests: function (validBidRequests, bidderRequest) { let vRequests = []; - let bidReq = { id: Math.random().toString(10).substring(2), imp: [] }; - + let vgdprConsent = null; + if (utils.deepAccess(bidderRequest, 'gdprConsent')) { + vgdprConsent = bidderRequest.gdprConsent; + } let vPrxClientTool = null; + let vSrvUrl = null; for (let vIdx = 0; vIdx < validBidRequests.length; vIdx++) { let bidRequest = validBidRequests[vIdx]; - - if (BANNER in bidRequest.mediaTypes !== true) continue; - if (bidRequest.mediaTypes.banner.sizes.length <= 0) continue; - - let vDim = bidRequest.mediaTypes.banner.sizes[0]; - vPrxClientTool = new ReloadClientTool({ prxVer: VERSION_ADAPTER, prxType: 'bd', - plcmID: bidRequest.params.plcmID, partID: bidRequest.params.partID, opdomID: bidRequest.params.opdomID, - bsrvID: bidRequest.params.bsrvID + bsrvID: bidRequest.params.bsrvID, + gdprObj: vgdprConsent, + mediaObj: bidRequest.mediaTypes, + wnd: utils.getWindowTop(), + rtop: utils.deepAccess(bidderRequest, 'refererInfo.reachedTop') || false }); - + if (vSrvUrl === null) vSrvUrl = vPrxClientTool.getSrvUrl(); let vImpression = { id: bidRequest.bidId, bidId: bidRequest.bidId, @@ -63,10 +58,7 @@ export const spec = { transactionId: bidRequest.transactionId, bidderRequestId: bidRequest.bidderRequestId, auctionId: bidRequest.auctionId, - banner: { - h: vDim[1], - w: vDim[0], ext: { type: bidRequest.params.type || 'pcm', pcmdata: vPrxClientTool.getPCMObj() @@ -75,12 +67,11 @@ export const spec = { }; bidReq.imp.push(vImpression); } - if (bidReq.imp.length > 0) { const payloadString = JSON.stringify(bidReq); vRequests.push({ method: 'POST', - url: vPrxClientTool.getSrvUrl(), + url: vSrvUrl, data: payloadString }); } @@ -94,64 +85,57 @@ export const spec = { */ interpretResponse: function (serverResponse, bidRequest) { const serverBody = serverResponse.body; - const bidResponses = []; - for (let vIdx = 0; vIdx < serverBody.seatbid.length; vIdx++) { let vSeatBid = serverBody.seatbid[vIdx]; - for (let vIdxBid = 0; vIdxBid < vSeatBid.bid.length; vIdxBid++) { let vBid = vSeatBid.bid[vIdxBid]; - let vPrxClientTool = new ReloadClientTool({ plcmID: vBid.ext.plcmID, partID: vBid.ext.partID, opdomID: vBid.ext.opdomID, bsrvID: vBid.ext.bsrvID }); - vPrxClientTool.setPCMObj(vBid.ext.pcmdata); - if (vPrxClientTool.getBP() > 0) { let bidResponse = { requestId: vBid.impid, ad: vPrxClientTool.getAM(), cpm: vPrxClientTool.getBP() / 100, - width: vBid.ext.banner.w, - height: vBid.ext.banner.h, + width: vPrxClientTool.getW(), + height: vPrxClientTool.getH(), creativeId: vBid.id, currency: vPrxClientTool.getBC(), ttl: 300, netRevenue: true }; bidResponses.push(bidResponse); + this.png[vBid.ext.adUnitCode] = vPrxClientTool.getPingUrl('bidwon'); } } } - return bidResponses; + }, + /** + * Register bidder specific code, which will execute if a bid from this bidder won the auction + * @param {Bid} The bid that won the auction + */ + onBidWon: function (bid) { + if (typeof this.png[bid.adUnitCode] !== 'string' || this.png[bid.adUnitCode] === '') return; + (new Image()).src = this.png[bid.adUnitCode]; } }; -/** - * Reload Client Tool - * @param {json} args - */ - function ReloadClientTool(args) { var that = this; - var _pcmClientVersion = '120'; var _pcmFilePref = 'prx_root_'; var _resFilePref = 'prx_pnws_'; - - var _pcmInputObjVers = '100'; - + var _pcmInputObjVers = '120'; var _instObj = null; var _status = 'NA'; var _message = ''; var _log = ''; - var _memFile = _getMemFile(); if (_memFile.status !== 'ok') { @@ -161,12 +145,12 @@ function ReloadClientTool(args) { that.getPCMObj = function () { return { thisVer: _pcmInputObjVers, - statStr: _memFile.statStr, plcmData: _getPlcmData(), - clntData: _getClientData(), + clntData: _getClientData(args.wnd, args.rtop), resultData: _getRD(), - + gdprObj: _getGdpr(), + mediaObj: _getMediaObj(), proxetString: null, dboData: null, plcmSett: null, @@ -210,32 +194,34 @@ function ReloadClientTool(args) { } }; + that.getMT = function () { + return _checkInstProp('mtype', 'dsp'); + }; + + that.getW = function () { + return _checkInstProp('width', 0); + }; + + that.getH = function () { + return _checkInstProp('height', 0); + }; + that.getBP = function () { - if (_instObj === null) return 0; - if (typeof _instObj === 'undefined') return 0; - if (_instObj.go !== true) return 0; - return _instObj.prc; + return _checkInstProp('prc', 0); }; that.getBC = function () { - if (_instObj === null) return 0; - if (typeof _instObj === 'undefined') return 0; - if (_instObj.go !== true) return 0; - return _instObj.cur; + return _checkInstProp('cur', 'USD'); }; that.getAM = function () { - if (_instObj === null) return null; - if (typeof _instObj === 'undefined') return null; - if (_instObj.go !== true) return null; - return _instObj.am; + return _checkInstProp('am', null); }; - that.getPM = function () { - if (_instObj === null) return null; - if (typeof _instObj === 'undefined') return null; - if (_instObj.go === true) return null; - return _instObj.pbm; + that.getPingUrl = function (pingName) { + var pingData = _checkInstProp('pingdata', {}); + if (pingData[pingName] !== 'undefined') return pingData[pingName]; + return ''; }; that.setRD = function (data) { @@ -254,6 +240,14 @@ function ReloadClientTool(args) { return _log; }; + function _checkInstProp (key, def) { + if (_instObj === null) return def; + if (typeof _instObj === 'undefined') return def; + if (_instObj.go !== true) return def; + if (typeof _instObj[key] === 'undefined') return def; + return _instObj[key]; + } + function _getPlcmData () { return { prxVer: args.prxVer, @@ -268,33 +262,37 @@ function ReloadClientTool(args) { }; } - function _getClientData () { + function _getClientData (wnd, rtop) { return { - version: 100, + version: 200, locTime: Date.now(), - - winInfo: _genWinInfo(), + winInfo: _winInf(wnd), envInfo: getEnvInfo(), - confined: detectConfined(), - protStr: _getProtocolString(), - - hostDomain: decodeURIComponent(window.location.host), - hostPagePath: decodeURIComponent(window.location.pathname), - hostPageUrl: decodeURIComponent(window.location.href), - hostPageTitle: document.title, + topw: rtop === true, + prot: wnd.document.location.protocol, + host: wnd.document.location.host, + title: wnd.document.title, }; - function _genWinInfo () { - var winInfo = { - physicalWidth: window.screen.width, - physicalHeight: window.screen.height, - screenWidth: window.screen.availWidth, - screenHeight: window.screen.availHeight, - windowWidth: window.innerWidth, - windowHeight: window.innerHeight, - bodyHeight: document.body.clientHeight + function _winInf (wnd) { + return { + phs: { + w: wnd.screen.width, + h: wnd.screen.height + }, + avl: { + w: wnd.screen.availWidth, + h: wnd.screen.availHeight + }, + inr: { + w: wnd.innerWidth, + h: wnd.innerHeight + }, + bdy: { + w: wnd.document.body.clientWidth, + h: wnd.document.body.clientHeight + } }; - return winInfo; } function getEnvInfo() { @@ -304,12 +302,6 @@ function ReloadClientTool(args) { appVersion: navigator.appVersion }; } - - function detectConfined () { - var confined = true; - try { if (window.top === window.self) confined = false; } catch (err) {} - return confined; - } } function _getMemFile () { @@ -369,8 +361,17 @@ function ReloadClientTool(args) { } } + function _getGdpr() { + return args.gdprObj; + } + + function _getMediaObj() { + return args.mediaObj; + } + function _getResltStatusFileName () { - return _resFilePref + args.plcmID + '_' + args.partID; + if (args.lmod === true) return _resFilePref + args.lplcmID + '_' + args.partID; + else return _resFilePref + args.plcmID + '_' + args.partID; } function _setItem (name, data) { diff --git a/test/spec/modules/reloadBidAdapter_spec.js b/test/spec/modules/reloadBidAdapter_spec.js index ebf7308caf2..674c810d48a 100644 --- a/test/spec/modules/reloadBidAdapter_spec.js +++ b/test/spec/modules/reloadBidAdapter_spec.js @@ -66,7 +66,7 @@ let getExt1ServerResponse = () => { 'testCase': 'A:00_B:100', 'opdomain': '1', 'checksum': '6378', - 'cmp': '0', + 'cpm': '0', 'bstfct': '100', 'totstop': 'false', 'pcmurl': 'bidsrv01.reload.net' @@ -82,6 +82,7 @@ let getExt1ServerResponse = () => { 'partID': 'prx_part', 'opdomID': '0', 'bsrvID': 1, + 'adUnitCode': '1b243858-3c53-43dc-9fdf-89f839ea4a0f', 'banner': {'w': 300, 'h': 250} })); } @@ -103,7 +104,7 @@ let getExt2ServerResponse = () => { 'testCase': 'A:00_B:100', 'opdomain': '1', 'checksum': '6378', - 'cmp': '0', + 'cpm': '0', 'bstfct': '100', 'totstop': 'false', 'pcmurl': 'bidsrv00.reload.net' @@ -117,6 +118,7 @@ let getExt2ServerResponse = () => { 'partID': 'prx_part', 'opdomID': '0', 'bsrvID': 1, + 'adUnitCode': '1b243858-3c53-43dc-9fdf-89f839ea4a0f', 'banner': {'w': 160, 'h': 600} })); } From 69123658115325eff1c7bcef9a8943cbcd36d566 Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Thu, 1 Aug 2019 11:52:15 +0300 Subject: [PATCH 130/436] AdkernelAdn adapter minor update (#4033) * Updated maintainer email * Minor refactoring & more unit tests * Updated config example --- modules/adkernelAdnBidAdapter.js | 36 +++++----- modules/adkernelAdnBidAdapter.md | 63 +++++++++-------- .../modules/adkernelAdnBidAdapter_spec.js | 70 +++++++++++++++---- 3 files changed, 107 insertions(+), 62 deletions(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 63321fb82ee..08842db37e3 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,11 +1,9 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {BANNER, VIDEO} from '../src/mediaTypes'; -import includes from 'core-js/library/fn/array/includes'; import {parse as parseUrl} from '../src/url'; const DEFAULT_ADKERNEL_DSP_DOMAIN = 'tag.adkernel.com'; -const VIDEO_TARGETING = ['mimes', 'protocols', 'api']; const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash', 'application/javascript']; const DEFAULT_PROTOCOLS = [2, 3, 5, 6]; const DEFAULT_APIS = [1, 2]; @@ -19,25 +17,22 @@ function buildImp(bidRequest) { id: bidRequest.bidId, tagid: bidRequest.adUnitCode }; - if (utils.deepAccess(bidRequest, `mediaTypes.banner`)) { - let sizes = canonicalizeSizesArray(bidRequest.mediaTypes.banner.sizes); + let bannerReq = utils.deepAccess(bidRequest, `mediaTypes.banner`); + let videoReq = utils.deepAccess(bidRequest, `mediaTypes.video`); + if (bannerReq) { + let sizes = canonicalizeSizesArray(bannerReq.sizes); imp.banner = { format: utils.parseSizesInput(sizes) } - } else if (utils.deepAccess(bidRequest, `mediaTypes.video`)) { - let size = canonicalizeSizesArray(bidRequest.mediaTypes.video.playerSize)[0]; + } else if (videoReq) { + let size = canonicalizeSizesArray(videoReq.playerSize)[0]; imp.video = { w: size[0], h: size[1], - mimes: DEFAULT_MIMES, - protocols: DEFAULT_PROTOCOLS, - api: DEFAULT_APIS + mimes: videoReq.mimes || DEFAULT_MIMES, + protocols: videoReq.protocols || DEFAULT_PROTOCOLS, + api: videoReq.api || DEFAULT_APIS }; - if (bidRequest.params.video) { - Object.keys(bidRequest.params.video) - .filter(param => includes(VIDEO_TARGETING, param)) - .forEach(param => imp.video[param] = bidRequest.params.video[param]); - } } return imp; } @@ -118,8 +113,11 @@ export const spec = { aliases: ['engagesimply'], isBidRequestValid: function(bidRequest) { - return 'params' in bidRequest && (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') && - typeof bidRequest.params.pubId === 'number' && 'mediaTypes' in bidRequest && ('banner' in bidRequest.mediaTypes || 'video' in bidRequest.mediaTypes); + return 'params' in bidRequest && + (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') && + typeof bidRequest.params.pubId === 'number' && + 'mediaTypes' in bidRequest && + ('banner' in bidRequest.mediaTypes || 'video' in bidRequest.mediaTypes); }, buildRequests: function(bidRequests, bidderRequest) { @@ -133,10 +131,8 @@ export const spec = { acc[host][pubId].push(curr); return acc; }, {}); - let auctionId = bidderRequest.auctionId; - let gdprConsent = bidderRequest.gdprConsent; - let transactionId = bidderRequest.transactionId; - let refererInfo = bidderRequest.refererInfo; + + let {auctionId, gdprConsent, transactionId, refererInfo} = bidderRequest; let requests = []; Object.keys(dispatch).forEach(host => { Object.keys(dispatch[host]).forEach(pubId => { diff --git a/modules/adkernelAdnBidAdapter.md b/modules/adkernelAdnBidAdapter.md index d69bf3b8998..c536ee1438c 100644 --- a/modules/adkernelAdnBidAdapter.md +++ b/modules/adkernelAdnBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: AdKernel ADN Bidder Adapter Module Type: Bidder Adapter -Maintainer: denis@adkernel.com +Maintainer: prebid-dev@adkernel.com ``` # Description @@ -14,32 +14,37 @@ Banner and video formats are supported. # Test Parameters ``` - var adUnits = [ - { - code: 'banner-ad-div', - sizes: [[300, 250], [300, 200]], - bids: [ - { - bidder: 'adkernelAdn', - params: { - pubId: 50357, - host: 'dsp-staging.adkernel.com' - } - } - ] - }, { - code: 'video-ad-player', - sizes: [640, 480], - bids: [ - { - bidder: 'adkernelAdn', - mediaType : 'video', - params: { - pubId: 50357, - host: 'dsp-staging.adkernel.com' - } - } - ] - } - ]; +var adUnits = [{ + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 200] // banner sizes + ], + } + }, + bids: [{ + bidder: 'adkernelAdn', + params: { + pubId: 50357, + host: 'dsp-staging.adkernel.com' + } + }] +}, { + code: 'video-ad-player', + mediaTypes: { + video: { + context: 'instream', // or 'outstream' + playerSize: [640, 480] // video player size + } + }, + bids: [{ + bidder: 'adkernelAdn', + params: { + pubId: 50357, + host: 'dsp-staging.adkernel.com' + } + }] +}]; ``` diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index 833a8e27f95..1147520131b 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -18,8 +18,7 @@ describe('AdkernelAdn adapter', function () { } }, adUnitCode: 'ad-unit-1', - }, - bid2_pub1 = { + }, bid2_pub1 = { bidder: 'adkernelAdn', transactionId: 'transact0', bidderRequestId: 'req0', @@ -34,8 +33,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] } } - }, - bid1_pub2 = { + }, bid1_pub2 = { bidder: 'adkernelAdn', transactionId: 'transact2', bidderRequestId: 'req1', @@ -60,17 +58,15 @@ describe('AdkernelAdn adapter', function () { mediaTypes: { video: { context: 'instream', - playerSize: [640, 300] - } - }, - adUnitCode: 'video_wrapper', - params: { - pubId: 7, - video: { + playerSize: [640, 300], mimes: ['video/mp4', 'video/webm'], api: [1, 2], protocols: [5, 6] } + }, + adUnitCode: 'video_wrapper', + params: { + pubId: 7 } }, bid_video2 = { bidder: 'adkernelAdn', @@ -85,11 +81,23 @@ describe('AdkernelAdn adapter', function () { context: 'instream' } }, - adUnitCode: 'video_wrapper2', params: { pubId: 7 } + }, bid_multiformat = { + bidder: 'adkernelAdn', + transactionId: 'f82c64b8-c602-42a4-9791-4a268f6559ed', + bidderRequestId: 'req-001', + auctionId: 'auc-001', + bidId: 'Bid_01', + sizes: [[300, 250], [300, 200]], + mediaTypes: { + banner: {sizes: [[300, 250], [300, 200]]}, + video: {context: 'instream', playerSize: [[640, 480]]} + }, + adUnitCode: 'ad-unit-1', + params: {pubId: 7} }; const response = { @@ -137,9 +145,11 @@ describe('AdkernelAdn adapter', function () { describe('input parameters validation', () => { it('empty request shouldn\'t generate exception', () => { - expect(spec.isBidRequestValid({bidderCode: 'adkernelAdn' + expect(spec.isBidRequestValid({ + bidderCode: 'adkernelAdn' })).to.be.equal(false); }); + it('request without pubid should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -148,6 +158,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); + it('request with invalid pubid should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -158,6 +169,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); + it('request with totally invalid host should be ignored', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -169,6 +181,7 @@ describe('AdkernelAdn adapter', function () { sizes: [[300, 250]] })).to.be.equal(false); }); + it('valid request should be accepted', () => { expect(spec.isBidRequestValid({ bidder: 'adkernelAdn', @@ -205,19 +218,24 @@ describe('AdkernelAdn adapter', function () { it('should have request id', function () { expect(tagRequest).to.have.property('id'); }); + it('should have transaction id', function () { expect(tagRequest).to.have.property('tid'); }); + it('should have sizes', function () { expect(tagRequest.imp[0].banner).to.have.property('format'); expect(tagRequest.imp[0].banner.format).to.be.eql(['300x250', '300x200']); }); + it('should have impression id', function () { expect(tagRequest.imp[0]).to.have.property('id', 'bidid_1'); }); + it('should have tagid', function () { expect(tagRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); + it('should create proper site block', function () { expect(tagRequest.site).to.have.property('page', 'https://example.com/index.html'); expect(tagRequest.site).to.have.property('secure', 1); @@ -256,16 +274,19 @@ describe('AdkernelAdn adapter', function () { expect(tagRequest.imp[0]).to.have.property('video'); expect(tagRequest.imp[1]).to.have.property('video'); }); + it('should have tagid', () => { expect(tagRequest.imp[0]).to.have.property('tagid', 'video_wrapper'); expect(tagRequest.imp[1]).to.have.property('tagid', 'video_wrapper2'); }); + it('should have size', () => { expect(tagRequest.imp[0].video).to.have.property('w', 640); expect(tagRequest.imp[0].video).to.have.property('h', 300); expect(tagRequest.imp[1].video).to.have.property('w', 1920); expect(tagRequest.imp[1].video).to.have.property('h', 1080); }); + it('should have video params', () => { expect(tagRequest.imp[0].video).to.have.property('mimes'); expect(tagRequest.imp[0].video.mimes).to.be.eql(['video/mp4', 'video/webm']); @@ -276,6 +297,21 @@ describe('AdkernelAdn adapter', function () { }); }); + describe('multiformat request building', function () { + let [_, tagRequests] = buildRequest([bid_multiformat]); + + it('should contain single request', function () { + expect(tagRequests).to.have.length(1); + expect(tagRequests[0].imp).to.have.length(1); + }); + + it('should contain banner-only impression', function () { + expect(tagRequests[0].imp).to.have.length(1); + expect(tagRequests[0].imp[0]).to.have.property('banner'); + expect(tagRequests[0].imp[0]).to.not.have.property('video'); + }); + }); + describe('requests routing', function () { it('should issue a request for each publisher', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid_video1]); @@ -285,6 +321,7 @@ describe('AdkernelAdn adapter', function () { expect(tagRequests[0].imp).to.have.length(1); expect(tagRequests[1].imp).to.have.length(1); }); + it('should issue a request for each host', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1, bid1_pub2]); expect(pbRequests).to.have.length(2); @@ -297,12 +334,15 @@ describe('AdkernelAdn adapter', function () { describe('responses processing', function () { let responses; + before(function () { responses = spec.interpretResponse({body: response}); }); + it('should parse all responses', function () { expect(responses).to.have.length(3); }); + it('should return fully-initialized bid-response', function () { let resp = responses[0]; expect(resp).to.have.property('bidderCode', 'adkernelAdn'); @@ -317,6 +357,7 @@ describe('AdkernelAdn adapter', function () { expect(resp).to.have.property('ad'); expect(resp.ad).to.have.string(''); }); + it('should return fully-initialized video bid-response', function () { let resp = responses[2]; expect(resp).to.have.property('bidderCode', 'adkernelAdn'); @@ -329,6 +370,7 @@ describe('AdkernelAdn adapter', function () { expect(resp).to.have.property('vastUrl', 'http://vast.com/vast.xml'); expect(resp).to.not.have.property('ad'); }); + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: response}]); expect(syncs).to.have.length(0); @@ -337,11 +379,13 @@ describe('AdkernelAdn adapter', function () { expect(syncs[0]).to.have.property('type', 'iframe'); expect(syncs[0]).to.have.property('url', 'https://dsp.adkernel.com/sync'); }); + it('should handle user-sync only response', function () { let [pbRequests, tagRequests] = buildRequest([bid1_pub1]); let resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); expect(resp).to.have.length(0); }); + it('shouldn\' fail on empty response', function () { let syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: ''}]); expect(syncs).to.have.length(0); From ce0b36434a8a27fe90a596e0afc8ccbb347afc54 Mon Sep 17 00:00:00 2001 From: OneTagDevOps <38786435+OneTagDevOps@users.noreply.github.com> Date: Fri, 2 Aug 2019 15:33:31 +0200 Subject: [PATCH 131/436] Minor bug fixing in onetagBidAdapter.js (#4054) Fixed a minor bug. Updated TTL in response to align the correct specifications. --- modules/onetagBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 72a88039fed..ce671772dad 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -24,7 +24,7 @@ function isBidRequestValid(bid) { return false; } - if (typeof bid.params.pubId !== 'string' || bid.sizes === 'undefined' || bid.sizes.length === 0) { + if (typeof bid.params.pubId !== 'string' || typeof bid.sizes === 'undefined' || bid.sizes.length === 0) { return false; } @@ -90,7 +90,7 @@ function interpretResponse(serverResponse, request) { netRevenue: false, mediaType: bids.type ? bids.type : BANNER, ad: bid.ad, - ttl: bid.ttl || 6000 + ttl: bid.ttl || 300 }); }); } From 1fac2e696a204e6d33df75d0acee71d5da146e4c Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Fri, 2 Aug 2019 19:18:05 +0530 Subject: [PATCH 132/436] Update karma to address vulnerabilities. (#4038) * update packages to fix vulns * upgrade node version to support advanced features * fix command gulp test --browserstack not exiting * fixes gulp view-coverage command failing * fix: command, gulp serve now keeps running without exiting * fix: error in package-lock.json * update README.md to reflect change in node version --- .circleci/config.yml | 2 +- README.md | 4 +- gulpfile.js | 28 +- package-lock.json | 2387 +++++++++++++++++++++--------------------- package.json | 8 +- 5 files changed, 1224 insertions(+), 1205 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 16bdd5b317e..85452b5aa88 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: build: docker: # specify the version you desire here - - image: circleci/node:7.10 + - image: circleci/node:9.0.0 # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images diff --git a/README.md b/README.md index 21e02ebee7f..a50c55f96ca 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ module.exports = { } ``` -Or for Babel 6 and/or Node v8.6.0 and less: +Or for Babel 6: ```javascript // you must manually install and specify the presets and plugins yourself options: { @@ -112,7 +112,7 @@ prebid.requestBids({ $ cd Prebid.js $ npm install -*Note:* You need to have `NodeJS` 6.x or greater installed. +*Note:* You need to have `NodeJS` 9.x or greater installed. *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. diff --git a/gulpfile.js b/gulpfile.js index a89f570e496..24c628ef228 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -205,18 +205,6 @@ function bundle(dev, moduleArr) { .pipe(gulpif(dev, sourcemaps.write('.'))); } -// Workaround for incompatibility between Karma & gulp callbacks. -// See https://github.com/karma-runner/gulp-karma/issues/18 for some related discussion. -function newKarmaCallback(done) { - return function (exitCode) { - if (exitCode) { - done(new Error('Karma tests failed with exit code ' + exitCode)); - } else { - done(); - } - } -} - // Run the unit tests. // // By default, this runs in headless chrome. @@ -248,6 +236,22 @@ function test(done) { } } +function newKarmaCallback(done) { + return function(exitCode) { + if (exitCode) { + done(new Error('Karma tests failed with exit code ' + exitCode)); + if (argv.browserstack) { + process.exit(exitCode); + } + } else { + done(); + if (argv.browserstack) { + process.exit(exitCode); + } + } + } +} + // If --file "" is given, the task will only run tests in the specified file. function testCoverage(done) { new KarmaServer(karmaConfMaker(true, false, false, argv.file), newKarmaCallback(done)).start(); diff --git a/package-lock.json b/package-lock.json index 06746ab8c41..1ed87be2492 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,45 +5,45 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { "@babel/highlight": "^7.0.0" } }, "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helpers": "^7.5.5", - "@babel/parser": "^7.5.5", + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.4.4", "jsesc": "^2.5.1", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -79,14 +79,14 @@ } }, "@babel/helper-define-map": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", - "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" } }, "@babel/helper-explode-assignable-expression": { @@ -129,12 +129,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", - "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { - "@babel/types": "^7.5.5" + "@babel/types": "^7.0.0" } }, "@babel/helper-module-imports": { @@ -147,17 +147,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", - "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", "@babel/template": "^7.4.4", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" + "@babel/types": "^7.4.4", + "lodash": "^4.17.11" } }, "@babel/helper-optimise-call-expression": { @@ -176,12 +176,12 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", "dev": true, "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.11" } }, "@babel/helper-remap-async-to-generator": { @@ -198,15 +198,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", - "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/helper-simple-access": { @@ -241,20 +241,20 @@ } }, "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", "dev": true, "requires": { "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -263,9 +263,9 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -279,16 +279,6 @@ "@babel/plugin-syntax-async-generators": "^7.2.0" } }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", - "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0" - } - }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", @@ -300,9 +290,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -339,15 +329,6 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", @@ -385,9 +366,9 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", - "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -405,27 +386,27 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", - "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.13" + "lodash": "^4.17.11" } }, "@babel/plugin-transform-classes": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", - "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.5.5", + "@babel/helper-define-map": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-replace-supers": "^7.4.4", "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" } @@ -440,9 +421,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", - "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -460,9 +441,9 @@ } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -516,37 +497,34 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", - "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-simple-access": "^7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", - "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-umd": { @@ -578,13 +556,13 @@ } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@babel/helper-replace-supers": "^7.1.0" } }, "@babel/plugin-transform-parameters": { @@ -684,45 +662,43 @@ } }, "@babel/preset-env": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", - "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", + "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/plugin-proposal-object-rest-spread": "^7.4.4", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-async-to-generator": "^7.4.4", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.5.5", - "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.4.4", "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.5.0", + "@babel/plugin-transform-destructuring": "^7.4.4", "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", "@babel/plugin-transform-for-of": "^7.4.4", "@babel/plugin-transform-function-name": "^7.4.4", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.5.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-modules-systemjs": "^7.4.4", "@babel/plugin-transform-modules-umd": "^7.2.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", + "@babel/plugin-transform-object-super": "^7.2.0", "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", "@babel/plugin-transform-regenerator": "^7.4.5", @@ -733,7 +709,7 @@ "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.5.5", + "@babel/types": "^7.4.4", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -753,30 +729,30 @@ } }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.13", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -853,6 +829,14 @@ "dev": true, "requires": { "samsam": "1.3.0" + }, + "dependencies": { + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + } } }, "@sinonjs/samsam": { @@ -872,6 +856,194 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -939,9 +1111,9 @@ } }, "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", "dev": true }, "after": { @@ -971,6 +1143,12 @@ "json-schema-traverse": "^0.3.0" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", @@ -1003,7 +1181,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "dev": true, + "optional": true }, "ansi-colors": { "version": "3.2.3", @@ -1092,6 +1271,12 @@ "default-require-extensions": "^1.0.0" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -1109,12 +1294,12 @@ }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } } } @@ -1778,15 +1963,6 @@ "babel-runtime": "^6.22.0" } }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -2726,15 +2902,15 @@ } }, "bfj": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", - "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", + "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", "dev": true, "requires": { - "bluebird": "^3.5.5", - "check-types": "^8.0.3", - "hoopy": "^0.1.4", - "tryer": "^1.0.1" + "bluebird": "^3.5.1", + "check-types": "^7.3.0", + "hoopy": "^0.1.2", + "tryer": "^1.0.0" } }, "big.js": { @@ -2841,12 +3017,6 @@ "toidentifier": "1.0.0" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3019,14 +3189,14 @@ } }, "browserslist": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", - "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", + "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000984", - "electron-to-chromium": "^1.3.191", - "node-releases": "^1.1.25" + "caniuse-lite": "^1.0.30000975", + "electron-to-chromium": "^1.3.164", + "node-releases": "^1.1.23" } }, "browserstack": { @@ -3039,15 +3209,30 @@ } }, "browserstack-local": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", - "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", + "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1", "is-running": "^2.0.0", "ps-tree": "=1.1.1", + "sinon": "^1.17.6", "temp-fs": "^0.9.9" + }, + "dependencies": { + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": ">=0.10.3 <1" + } + } } }, "buffer": { @@ -3124,6 +3309,54 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, + "cacache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", + "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3181,7 +3414,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -3247,9 +3480,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000987", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000987.tgz", - "integrity": "sha512-O3VrjtRMTxoU5Cn5/QSmXeIR1gkVps4j9jqfIm4FLaQ5JzqBlVjMUG1xWnoYFv8N+H3Lp++aa05TekyIbjHL7g==", + "version": "1.0.30000975", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", + "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", "dev": true }, "caseless": { @@ -3336,9 +3569,9 @@ "dev": true }, "check-types": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", - "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", "dev": true }, "chokidar": { @@ -3361,6 +3594,21 @@ "upath": "^1.1.1" } }, + "chownr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3547,15 +3795,6 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3757,6 +3996,31 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -3790,9 +4054,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true } } @@ -3810,13 +4074,13 @@ "dev": true }, "coveralls": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", - "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", + "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", "dev": true, "requires": { "growl": "~> 1.10.0", - "js-yaml": "^3.13.1", + "js-yaml": "^3.11.0", "lcov-parse": "^0.0.10", "log-driver": "^1.2.7", "minimist": "^1.2.0", @@ -3966,6 +4230,12 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3986,9 +4256,9 @@ } }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", "dev": true }, "date-now": { @@ -4745,15 +5015,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.205", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.205.tgz", - "integrity": "sha512-VV+f2FVeFI5D/slUD7A3V1lTMDkQTUGWYH2dZGAijIutN5Aga4Fn/Hv4Gc+60OpXFVLYIq5HpXb2cG6NrGGQaA==", + "version": "1.3.164", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", + "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", "dev": true }, "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4795,7 +5065,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4809,7 +5079,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4825,7 +5095,7 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -4851,7 +5121,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -5228,9 +5498,9 @@ } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", + "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5307,9 +5577,9 @@ } }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", + "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -5319,8 +5589,8 @@ "eslint-import-resolver-node": "^0.3.2", "eslint-module-utils": "^2.4.0", "has": "^1.0.3", + "lodash": "^4.17.11", "minimatch": "^3.0.4", - "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", "resolve": "^1.11.0" }, @@ -5558,7 +5828,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5627,40 +5897,6 @@ } } }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - } - } - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5711,34 +5947,10 @@ } } }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - }, - "dependencies": { - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -5798,13 +6010,13 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.4", + "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -6028,6 +6240,12 @@ "detect-libc": "^1.0.3" } }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -6047,12 +6265,6 @@ "object-assign": "^4.0.1" } }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6295,6 +6507,15 @@ "mime-types": "^2.1.12" } }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "~1.1" + } + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -6377,6 +6598,18 @@ "through2": "^2.0.3" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", @@ -6422,7 +6655,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6443,12 +6677,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6463,17 +6699,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6590,7 +6829,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6602,6 +6842,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6616,6 +6857,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6623,12 +6865,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6647,6 +6891,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6727,7 +6972,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6739,6 +6985,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6824,7 +7071,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6860,6 +7108,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6879,6 +7128,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6922,19 +7172,21 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, "fun-hooks": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", - "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", + "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" }, "function-bind": { "version": "1.1.1", @@ -7053,42 +7305,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -7232,9 +7448,9 @@ } }, "graceful-fs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "grapheme-splitter": { @@ -7683,7 +7899,7 @@ "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", "dev": true, "requires": { "ansi-colors": "^2.0.5", @@ -7700,7 +7916,7 @@ "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", + "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", "dev": true } } @@ -7801,22 +8017,22 @@ "dev": true }, "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", + "lodash._reinterpolate": "~3.0.0", "lodash.templatesettings": "^4.0.0" } }, "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0" + "lodash._reinterpolate": "~3.0.0" } } } @@ -7878,9 +8094,9 @@ } }, "gulp-match": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", - "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", "dev": true, "requires": { "minimatch": "^3.0.3" @@ -8157,9 +8373,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -8427,7 +8643,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { @@ -8435,14 +8651,6 @@ "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } } }, "http-parser-js": { @@ -8480,12 +8688,12 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { - "agent-base": "^4.3.0", + "agent-base": "^4.1.0", "debug": "^3.1.0" }, "dependencies": { @@ -8521,6 +8729,12 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8559,9 +8773,9 @@ } }, "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { @@ -8698,6 +8912,12 @@ "is-decimal": "^1.0.0" } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8782,21 +9002,6 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -8824,6 +9029,12 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -8886,18 +9097,6 @@ "isobject": "^3.0.1" } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -9132,12 +9331,12 @@ }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } } } @@ -9414,28 +9613,27 @@ "dev": true }, "karma": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz", + "integrity": "sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "chokidar": "^2.0.3", + "braces": "^3.0.2", + "chokidar": "^3.0.0", "colors": "^1.1.0", - "combine-lists": "^1.0.0", "connect": "^3.6.0", - "core-js": "^2.2.0", + "core-js": "^3.1.3", "di": "^0.0.1", "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", + "lodash": "^4.17.11", + "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -9449,12 +9647,108 @@ "useragent": "2.3.0" }, "dependencies": { + "anymatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz", + "integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", + "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", + "dev": true, + "requires": { + "anymatch": "^3.0.1", + "braces": "^3.0.2", + "fsevents": "^2.0.6", + "glob-parent": "^5.0.0", + "is-binary-path": "^2.1.0", + "is-glob": "^4.0.1", + "normalize-path": "^3.0.0", + "readdirp": "^3.1.1" + } + }, + "core-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", + "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, + "readdirp": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.1.tgz", + "integrity": "sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -9469,6 +9763,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -9636,12 +9939,12 @@ }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } } } @@ -10045,33 +10348,16 @@ } }, "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" } }, "loglevelnext": { @@ -10085,9 +10371,9 @@ } }, "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, "longest": { @@ -10180,6 +10466,12 @@ "kind-of": "^6.0.2" } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10263,12 +10555,6 @@ } } }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -10646,10 +10932,28 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -10682,7 +10986,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10828,6 +11132,31 @@ } } }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11040,13 +11369,22 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true - } - } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } }, "node-releases": { - "version": "1.1.26", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", - "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", + "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", "dev": true, "requires": { "semver": "^5.3.0" @@ -11232,6 +11570,18 @@ "isobject": "^3.0.0" } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11252,27 +11602,6 @@ "make-iterator": "^1.0.0" } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -11292,18 +11621,6 @@ "make-iterator": "^1.0.0" } }, - "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -11366,7 +11683,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11493,6 +11810,17 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -11565,9 +11893,9 @@ } }, "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", + "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -11685,35 +12013,6 @@ "ini": "^1.3.3" } }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -11913,18 +12212,18 @@ "sha.js": "^2.4.8" } }, - "pbkdf2-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", - "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", - "dev": true - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, "pidtree": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", @@ -12008,12 +12307,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12033,9 +12326,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "progress": { @@ -12044,6 +12337,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12088,9 +12387,9 @@ "dev": true }, "psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==", + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", + "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", "dev": true }, "public-encrypt": { @@ -12192,25 +12491,6 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12386,23 +12666,14 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", + "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", "dev": true, "requires": { "private": "^0.1.6" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -12414,9 +12685,9 @@ } }, "regexp-tree": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", - "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", + "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", "dev": true }, "regexpp": { @@ -12731,9 +13002,9 @@ "dev": true }, "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -12841,6 +13112,15 @@ "is-promise": "^2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -12884,9 +13164,9 @@ "dev": true }, "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", "dev": true }, "schema-utils": { @@ -12963,6 +13243,12 @@ } } }, + "serialize-javascript": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -13025,13 +13311,13 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", - "inherits": "2.0.4", + "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" @@ -13187,6 +13473,12 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true + }, + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true } } }, @@ -13330,7 +13622,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", "dev": true, "requires": { "debug": "~3.1.0", @@ -13344,7 +13636,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13367,7 +13659,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", "dev": true, "requires": { "backo2": "1.0.2", @@ -13395,7 +13687,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13411,7 +13703,7 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13429,7 +13721,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -13537,14 +13829,14 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -13583,6 +13875,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -13678,7 +13979,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -13695,6 +13996,16 @@ "readable-stream": "^2.0.2" } }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", @@ -13721,17 +14032,27 @@ "dev": true }, "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" }, "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -13740,6 +14061,26 @@ "requires": { "ms": "^2.1.1" } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } } } }, @@ -13940,9 +14281,9 @@ } }, "ternary-stream": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", - "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", "dev": true, "requires": { "duplexify": "^3.5.0", @@ -13951,6 +14292,102 @@ "through2": "^2.0.1" } }, + "terser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz", + "integrity": "sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "dev": true, + "requires": { + "cacache": "^11.3.2", + "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", + "loader-utils": "^1.2.3", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.0.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14205,6 +14642,12 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14285,7 +14728,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true + "dev": true, + "optional": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", @@ -14445,6 +14889,24 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -14515,6 +14977,12 @@ "unist-util-is": "^3.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -14656,7 +15124,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14664,20 +15132,16 @@ } }, "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", + "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", "dev": true, "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "inherits": "2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" } }, "util-deprecate": { @@ -15069,9 +15533,9 @@ }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -15081,18 +15545,18 @@ } }, "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.14" + "lodash": "^4.17.11" } }, "camelcase": { @@ -15385,9 +15849,9 @@ } }, "webpack-bundle-analyzer": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", - "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", + "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -15399,16 +15863,16 @@ "express": "^4.16.3", "filesize": "^3.6.1", "gzip-size": "^5.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.10", "mkdirp": "^0.5.1", "opener": "^1.5.1", "ws": "^6.0.0" }, "dependencies": { "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, "ejs": { @@ -15428,36 +15892,9 @@ } } }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", - "dev": true, - "requires": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, - "dependencies": { - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -15509,556 +15946,125 @@ } }, "webpack-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", - "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", + "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", "dev": true, "requires": { - "gulp-util": "^3.0.7", + "fancy-log": "^1.3.3", "lodash.clone": "^4.3.2", "lodash.some": "^4.2.2", - "memory-fs": "^0.3.0", + "memory-fs": "^0.4.1", + "plugin-error": "^1.0.1", + "supports-color": "^5.5.0", "through": "^2.3.8", - "vinyl": "^1.1.0", - "webpack": "^1.12.9" + "vinyl": "^2.1.0", + "webpack": "^4.26.1" }, "dependencies": { "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "browserify-aes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", - "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true, - "requires": { - "inherits": "^2.0.1" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "~0.2.0" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "dev": true }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, - "crypto-browserify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", - "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "dev": true, - "requires": { - "browserify-aes": "0.4.0", - "pbkdf2-compat": "2.0.1", - "ripemd160": "0.2.0", - "sha.js": "2.2.6" - } - }, "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, - "dependencies": { - "memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", - "dev": true - } + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", - "dev": true - }, - "interpret": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", - "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { + "fast-deep-equal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - }, - "memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "node-libs-browser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", - "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.1.4", - "buffer": "^4.9.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "0.0.1", - "os-browserify": "^0.2.0", - "path-browserify": "0.0.0", - "process": "^0.11.0", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.0.5", - "stream-browserify": "^2.0.1", - "stream-http": "^2.3.1", - "string_decoder": "^0.10.25", - "timers-browserify": "^2.0.2", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", - "dev": true - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "ripemd160": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", - "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", - "dev": true - }, - "sha.js": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", - "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "dev": true, - "requires": { - "async": "^0.9.0", - "chokidar": "^1.0.0", - "graceful-fs": "^4.1.2" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - } - } - }, "webpack": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", - "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true, - "requires": { - "acorn": "^3.0.0", - "async": "^1.3.0", - "clone": "^1.0.2", - "enhanced-resolve": "~0.9.0", - "interpret": "^0.6.4", - "loader-utils": "^0.2.11", - "memory-fs": "~0.3.0", + "version": "4.36.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.36.1.tgz", + "integrity": "sha512-Ej01/N9W8DVyhEpeQnbUdGvOECw0L46FxS12cCOs8gSK7bhUlrbHRnWkjiXckGlHjUrmL89kDpTRIkUk6Y+fKg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", "mkdirp": "~0.5.0", - "node-libs-browser": "^0.7.0", - "optimist": "~0.6.0", - "supports-color": "^3.1.0", - "tapable": "~0.1.8", - "uglify-js": "~2.7.3", - "watchpack": "^0.2.1", - "webpack-core": "~0.6.9" - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^1.0.0", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" } } } @@ -16122,6 +16128,15 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", @@ -16193,9 +16208,9 @@ "dev": true }, "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, "y18n": { diff --git a/package.json b/package.json index cb921f61bed..d028e6049a1 100755 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.2.0", "eslint-plugin-node": "^5.1.0", + "eslint-plugin-prebid": "file:./plugins/eslint", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", - "eslint-plugin-prebid": "file:./plugins/eslint", "execa": "^1.0.0", "faker": "^3.1.0", "fs.extra": "^1.3.2", @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^3.1.3", + "karma": "^4.2.0", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -76,7 +76,7 @@ "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.31", "karma-webpack": "^3.0.5", - "lodash": "^4.17.4", + "lodash": "^4.17.15", "mocha": "^5.0.0", "opn": "^5.4.0", "querystringify": "0.0.3", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^3.2.0", + "webpack-stream": "^5.2.1", "yargs": "^1.3.1" }, "dependencies": { From e39c50b205ec1499e4030507f95657cd8329b377 Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Fri, 2 Aug 2019 22:01:11 +0300 Subject: [PATCH 133/436] New adkernel adapter aliases (#4057) --- modules/adkernelBidAdapter.js | 9 ++++++++- test/spec/modules/adkernelBidAdapter_spec.js | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 02b9d2a7967..7c48458f474 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -5,6 +5,13 @@ import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; import {parse as parseUrl} from '../src/url'; +/* + * In case you're AdKernel whitelable platform's client who needs branded adapter to + * work with Adkernel platform - DO NOT COPY THIS ADAPTER UNDER NEW NAME + * + * Please contact prebid@adkernel.com and we'll add your adapter as an alias. + */ + const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', 'pos', 'api', 'ext']; @@ -16,7 +23,7 @@ const VERSION = '1.3'; export const spec = { code: 'adkernel', - aliases: ['headbidding'], + aliases: ['headbidding', 'adsolut', 'oftmediahb'], supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index a00f07603ee..621b9971304 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -379,8 +379,8 @@ describe('Adkernel adapter', function () { describe('adapter configuration', () => { it('should have aliases', () => { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.be.equal('headbidding'); + expect(spec.aliases).to.have.lengthOf(3); + expect(spec.aliases).to.be.eql(['headbidding', 'adsolut', 'oftmediahb']); }); }); }); From 4d94fd169b47adecb0a705ff19dff6e4d4de0146 Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Mon, 5 Aug 2019 21:26:36 +0530 Subject: [PATCH 134/436] adding supply chain Object feature (#4051) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json * adding schain object --- modules/oneVideoBidAdapter.js | 13 +++++++++++++ modules/oneVideoBidAdapter.md | 4 +++- test/spec/modules/oneVideoBidAdapter_spec.js | 16 +++++++++++++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index c05158f28c4..a4ea4c86e03 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -196,6 +196,19 @@ function getRequestData(bid, consentData) { if (bid.params.site && bid.params.site.id) { bidData.site.id = bid.params.site.id } + if (bid.params.video.sid) { + bidData.source = { + ext: { + schain: { + complete: 1, + nodes: [{ + sid: bid.params.video.sid, + rid: bidData.id, + }] + } + } + } + } if (isConsentRequired(consentData)) { bidData.regs = { diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md index 6e34d245c3e..c8c4d87f9cb 100644 --- a/modules/oneVideoBidAdapter.md +++ b/modules/oneVideoBidAdapter.md @@ -33,7 +33,9 @@ Connects to One Video demand source to fetch bids. position: 1, delivery: [2], playbackmethod: [1,5], - placement: 123 + placement: 123, + sid: , + }, }, site: { id: 1, diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 09118bba1d2..09ca6217fe2 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -30,7 +30,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123 + placement: 123, + sid: 134 }, site: { id: 1, @@ -65,7 +66,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123 + placement: 123, + sid: 134 } }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); @@ -81,7 +83,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123 + placement: 123, + sid: 134 }, pubId: 'brxd' }; @@ -196,5 +199,12 @@ describe('OneVideoBidAdapter', function () { const request = spec.buildRequests([ bidRequest ], bidderRequest); expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); }); + + it('should send schain object', function () { + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + expect(data.source.ext.schain.nodes[0].sid).to.equal(bidRequest.params.video.sid); + expect(data.source.ext.schain.nodes[0].rid).to.equal(data.id); + }); }); }); From e8a9131992d948c2e926f8d9f492a704a28b2e6e Mon Sep 17 00:00:00 2001 From: Sharath N Date: Tue, 6 Aug 2019 19:07:15 +0530 Subject: [PATCH 135/436] Adding new BidAdapter 'eywamedia' (#4055) * Adding new BidAdapter 'eywamedia' * removed unused import * removed unused variables * removed unused import * removed unused import - my bad! --- modules/eywamediaBidAdapter.js | 181 +++++++++++++ modules/eywamediaBidAdapter.md | 37 +++ test/spec/modules/eywamediaBidAdapter_spec.js | 253 ++++++++++++++++++ 3 files changed, 471 insertions(+) create mode 100644 modules/eywamediaBidAdapter.js create mode 100644 modules/eywamediaBidAdapter.md create mode 100644 test/spec/modules/eywamediaBidAdapter_spec.js diff --git a/modules/eywamediaBidAdapter.js b/modules/eywamediaBidAdapter.js new file mode 100644 index 00000000000..543775dc3aa --- /dev/null +++ b/modules/eywamediaBidAdapter.js @@ -0,0 +1,181 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = 'eywamedia'; +const CURRENCY = 'USD'; +const VERSION = '1.0.0'; +const TIME_TO_LIVE = 360; +const NET_REVENUE = true; +const COOKIE_NAME = 'emaduuid'; +const UUID_LEN = 36; +const SERVER_ENDPOINT = 'https://adtarbostg.eywamedia.com/auctions/prebidjs/3000'; +const localWindow = getTopWindow(); + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner'], + /** + * Determines whether or not the given bid request is valid. + * @param {object} bid, bid to validate + * @return boolean, true if valid, otherwise false + */ + isBidRequestValid: function(bid) { + return !!(bid.params.publisherId); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. + * @return requestPayload Info describing the request to the server. + */ + buildRequests: function(bidRequests, bidRequest) { + const device = getDeviceInfo(); + const site = getSiteInfo(); + const user = getUserInfo(); + + let requestPayload = { + id: utils.generateUUID(), + publisherId: bidRequests[0].params.publisherId, + device: device, + site: site, + user: user, + bidPayload: bidRequests, + cacheBust: new Date().getTime().toString(), + adapterVersion: VERSION, + tmax: bidRequest.timeout + }; + + return { + method: 'POST', + url: SERVER_ENDPOINT, + options: { + contentType: 'application/json' + }, + data: requestPayload + } + }, + + /** + * Makes Eywamedia Ad Server response compatible to Prebid specs + * @param serverResponse successful response from Ad Server + * @param bidderRequest original bidRequest + * @return {Bid[]} an array of bids + */ + interpretResponse: function (serverResponse, bidRequest) { + var bidObject, response; + var bidRespones = []; + var responses = serverResponse.body; + for (var i = 0; i < responses.length; i++) { + response = responses[i]; + bidObject = { + requestId: response.bidId, + cpm: response.cpm, + width: parseInt(response.width), + height: parseInt(response.height), + creativeId: response.bidId, + currency: CURRENCY, + netRevenue: NET_REVENUE, + ttl: TIME_TO_LIVE, + ad: response.ad, + bidderCode: BIDDER_CODE, + transactionId: response.transactionId, + mediaType: response.respType, + }; + bidRespones.push(bidObject); + } + return bidRespones; + } +} +registerBidder(spec); + +/*************************************** + * Helper Functions + ***************************************/ + +/** + * get device type + */ +function getDeviceType() { + let ua = navigator.userAgent; + // Tablets must be checked before phones. + if ((/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i).test(ua)) { + return 5; // "Tablet" + } + if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/).test(ua)) { + return 4; // "Phone" + } + return 2; // Personal Computers +}; + +/** + * get device info + */ +function getDeviceInfo() { + const language = navigator.language; + return { + ua: navigator.userAgent, + language: navigator[language], + devicetype: getDeviceType(), + dnt: utils.getDNT(), + geo: {}, + js: 1 + }; +}; + +/** + * get site info + */ +function getSiteInfo() { + const topLocation = utils.getTopWindowLocation(); + return { + domain: topLocation.hostname, + page: topLocation.href, + referrer: utils.getTopWindowReferrer(), + desc: getPageDescription(), + title: localWindow.document.title, + }; +}; + +/** + * get user info + */ +function getUserInfo() { + return { + id: getUserID(), + }; +}; + +/** + * get user Id + */ +const getUserID = () => { + const i = document.cookie.indexOf(COOKIE_NAME); + + if (i === -1) { + const uuid = utils.generateUUID(); + document.cookie = `${COOKIE_NAME}=${uuid}; path=/`; + return uuid; + } + + const j = i + COOKIE_NAME.length + 1; + return document.cookie.substring(j, j + UUID_LEN); +}; + +/** + * get page description + */ +function getPageDescription() { + if (document.querySelector('meta[name="description"]')) { + return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + } else { + return ''; + } +}; + +function getTopWindow() { + try { + return window.top; + } catch (e) { + return window; + } +}; diff --git a/modules/eywamediaBidAdapter.md b/modules/eywamediaBidAdapter.md new file mode 100644 index 00000000000..76b9b032c1b --- /dev/null +++ b/modules/eywamediaBidAdapter.md @@ -0,0 +1,37 @@ +# Overview + +``` +Module Name: Eywamedia Bid Adapter +Module Type: Bidder Adapter +Maintainer: sharath@eywamedia.com +Note: Our ads will only render in mobile and desktop +``` + +# Description + +Connects to Eywamedia Ad Server for bids. + +Eywamedia bid adapter supports Banners. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300,600]], + bids: [{ + bidder: 'eywamedia', + params: { + publisherId: 'f63a2362-5aa4-4829-bbd2-2678ced8b63e', //Required - GUID (may include numbers and characters) + bidFloor: 0.50, // optional + cats: ["iab1-1","iab23-2"], // optional + keywords: ["sports", "cricket"], // optional + lat: 12.33333, // optional + lon: 77.32322, // optional + locn: "country$region$city$zip" // optional + } + }] + } +]; +``` diff --git a/test/spec/modules/eywamediaBidAdapter_spec.js b/test/spec/modules/eywamediaBidAdapter_spec.js new file mode 100644 index 00000000000..945c0dd0d01 --- /dev/null +++ b/test/spec/modules/eywamediaBidAdapter_spec.js @@ -0,0 +1,253 @@ +import { expect } from 'chai'; +import { spec } from 'modules/eywamediaBidAdapter'; + +describe('EywamediaAdapter', function () { + let serverResponse, bidRequests, bidRequest, bidResponses; + const ENDPOINT = 'https://adtarbostg.eywamedia.com/auctions/prebidjs/3000'; + + bidRequests = [ + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[300, 250]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d671', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + }, + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[728, 90]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d672', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + } + ]; + + bidRequest = { + 'auctionId': 'c88115a4-7e71-43d0-9c96-a9b43ebd143d', + 'auctionStart': 1564725164517, + 'bidderCode': 'eywamedia', + 'bidderRequestId': '191afa18994fdd', + 'bids': [], + 'refererInfo': { + 'canonicalUrl': '', + 'numIframes': 0, + 'reachedTop': true, + 'referer': '' + }, + 'stack': [ + '' + ], + 'start': 1564725164520, + 'timeout': 3000 + }; + + let testBid = { + 'bidder': 'eywamedia', + 'params': { + 'publisherId': '1234_abcd' + } + }; + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + assert(spec.isBidRequestValid(testBid)); + }); + + it('should return false when required params are missing', function () { + testBid.params = { + test: '231212312' + }; + assert.isFalse(spec.isBidRequestValid(testBid)); + }); + }); + + describe('buildRequests', function () { + it('should attempt to send bid requests to the endpoint via POST', function () { + const requests = spec.buildRequests(bidRequests, bidRequest); + expect(requests.method).to.equal('POST'); + expect(requests.url).to.be.equal(ENDPOINT); + }); + + it('should not blow up if crumbs is undefined', function () { + let bidArray = [ + { ...testBid, crumbs: undefined } + ] + expect(function () { spec.buildRequests(bidArray, bidRequest) }).not.to.throw() + }) + + it('should return true when required params found', function () { + testBid.params.publisherId = '1234_abcd'; + assert(spec.isBidRequestValid(testBid)); + }); + }); + + describe('interpretResponse', function () { + beforeEach(function () { + serverResponse = { + 'body': + [ + { + 'ad': '', + 'adSlot': '', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'adUrl': 'http://eywamedia.com', + 'bidId': '28b09d0543d671', + 'bidder': 'eywamedia', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'height': 250, + 'requestTimestamp': 1564725162, + 'respType': 'banner', + 'size': '300X250', + 'statusMessage': 'Bid available', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'usesGenericKeys': true, + 'width': 300 + }, + { + 'ad': '', + 'adSlot': '', + 'adUnitCode': 'div-gpt-ad-1460505748561-1', + 'adUrl': 'http://eywamedia.com', + 'bidId': '28b09d0543d672', + 'bidder': 'eywamedia', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'height': 90, + 'requestTimestamp': 1564725164, + 'respType': 'banner', + 'size': '728X90', + 'statusMessage': 'Bid available', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'usesGenericKeys': true, + 'width': 728 + } + ], + 'headers': 'header?' + }; + + bidRequest = { + 'data': + { + 'bidPayload': + [ + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[300, 250]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d671', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + }, + { + 'auctionId': 'fc917230-a5e1-4a42-b7d9-8fb776124e43', + 'sizes': [[728, 90]], + 'bidRequestsCount': 1, + 'params': { + 'publisherId': '1234_abcd' + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[728, 90]] + } + }, + 'crumbs': { + 'pubcid': '8b640d4e-1f6d-4fd3-b63f-2570572d8100' + }, + 'bidId': '28b09d0543d672', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'src': 'client', + 'bidder': 'eywamedia', + 'bidderRequestId': '14d8cbc769114b' + } + ] + } + }; + bidResponses = [ + { + 'ad': '', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'creativeId': '28b09d0543d671', + 'currency': 'USD', + 'height': 250, + 'mediaType': 'banner', + 'netRevenue': true, + 'requestId': '28b09d0543d671', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b1', + 'ttl': 360, + 'width': 300 + }, + { + 'ad': '', + 'bidderCode': 'eywamedia', + 'cpm': 1, + 'creativeId': '28b09d0543d672', + 'currency': 'USD', + 'height': 90, + 'mediaType': 'banner', + 'netRevenue': true, + 'requestId': '28b09d0543d672', + 'transactionId': 'd909c39c-ecc9-41a4-897c-2d2fdfdf41b2', + 'ttl': 360, + 'width': 728 + } + ] + }); + + it('should respond with empty response when there is empty serverResponse', function () { + let result = spec.interpretResponse({ body: {} }, bidRequest); + assert.deepEqual(result, []); + }); + + it('should respond with multile response when there is multiple serverResponse', function () { + let result = spec.interpretResponse(serverResponse, bidRequest); + assert.deepEqual(result, bidResponses); + }); + }); +}); From ee7bbf2a72aa91e7c6d29ed982c27c6b0487a1dd Mon Sep 17 00:00:00 2001 From: VideoReach <49446045+VideoReach@users.noreply.github.com> Date: Tue, 6 Aug 2019 18:10:36 +0200 Subject: [PATCH 136/436] Change Domain to videoreach.com (#4056) --- modules/videoreachBidAdapter.js | 4 ++-- modules/videoreachBidAdapter.md | 2 +- test/spec/modules/videoreachBidAdapter_spec.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/videoreachBidAdapter.js b/modules/videoreachBidAdapter.js index 03290c9b79c..363355292ca 100644 --- a/modules/videoreachBidAdapter.js +++ b/modules/videoreachBidAdapter.js @@ -1,7 +1,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; const utils = require('../src/utils'); const BIDDER_CODE = 'videoreach'; -const ENDPOINT_URL = '//a.videoreach.de/hb/'; +const ENDPOINT_URL = '//a.videoreach.com/hb/'; export const spec = { code: BIDDER_CODE, @@ -65,7 +65,7 @@ export const spec = { getUserSyncs: function(syncOptions, responses, gdprConsent) { const syncs = []; - if (syncOptions.pixelEnabled && responses.length) { + if (syncOptions.pixelEnabled && responses.length && responses[0].body.responses.length) { const SyncPixels = responses[0].body.responses[0].sync; let params = ''; diff --git a/modules/videoreachBidAdapter.md b/modules/videoreachBidAdapter.md index cdd1ecc04c5..a68c9b26aeb 100644 --- a/modules/videoreachBidAdapter.md +++ b/modules/videoreachBidAdapter.md @@ -2,7 +2,7 @@ **Module Name**: Video Reach Bidder Adapter **Module Type**: Bidder Adapter -**Maintainer**: hello@videoreach.de +**Maintainer**: hello@videoreach.com # Description diff --git a/test/spec/modules/videoreachBidAdapter_spec.js b/test/spec/modules/videoreachBidAdapter_spec.js index b74a0236551..237821f7102 100644 --- a/test/spec/modules/videoreachBidAdapter_spec.js +++ b/test/spec/modules/videoreachBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/videoreachBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT_URL = '//a.videoreach.de/hb/'; +const ENDPOINT_URL = '//a.videoreach.com/hb/'; describe('videoreachBidAdapter', function () { describe('isBidRequestValid', function () { @@ -86,7 +86,7 @@ describe('videoreachBidAdapter', function () { 'cpm': 10.0, 'width': '1', 'height': '1', - 'ad': '', + 'ad': '', 'ttl': 360, 'creativeId': '5cb5dc9375c0e', 'netRevenue': true, From 90942e88fd6bef8d247843b4efc96a345b7b775c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Tue, 6 Aug 2019 18:47:43 +0200 Subject: [PATCH 137/436] Add instream & outstream video support to Criteo adapter (#4037) * assign adapter version * Mapped video parameter from prebid.js to cdb * Mapped video parameter from prebid.js to cdb * Ensure that context is consistent with placement and that we do not support longform * updated playersize property name * fixed size parsing to be able to handle single player size as well as several * Changed playersize to plural playersizes in CDB contract * Use displayurl instead of creative as we want to fetch the direct url vast cache instead a vast wrapper --- modules/criteoBidAdapter.js | 106 ++++- test/spec/modules/criteoBidAdapter_spec.js | 431 ++++++++++++++++++++- 2 files changed, 530 insertions(+), 7 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 0507ba428be..56e22e45017 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,13 +1,14 @@ import { loadExternalScript } from '../src/adloader'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; +import { BANNER, VIDEO } from '../src/mediaTypes'; import { parse } from '../src/url'; import * as utils from '../src/utils'; import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -import { config } from '../src/config'; -const ADAPTER_VERSION = 17; +const ADAPTER_VERSION = 19; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -30,14 +31,27 @@ OmOSj0/qnYTAYCu0cR5LiyWG79KlIgUyMbp92ulGg24gAyGrVn4+v/4c53WlOEUp /** @type {BidderSpec} */ export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, VIDEO ], /** * @param {object} bid * @return {boolean} */ - isBidRequestValid: bid => ( - !!(bid && bid.params && (bid.params.zoneId || bid.params.networkId)) - ), + isBidRequestValid: (bid) => { + // either one of zoneId or networkId should be set + if (!(bid && bid.params && (bid.params.zoneId || bid.params.networkId))) { + return false; + } + + // video media types requires some mandatory params + if (hasVideoMediaType(bid)) { + if (!hasValidVideoMediaType(bid)) { + return false; + } + } + + return true; + }, /** * @param {BidRequest[]} bidRequests @@ -112,6 +126,9 @@ export const spec = { } if (slot.native) { bid.ad = createNativeAd(bidId, slot.native, bidRequest.params.nativeCallback); + } else if (slot.video) { + bid.vastUrl = slot.displayurl; + bid.mediaType = VIDEO; } else { bid.ad = slot.creative; } @@ -225,7 +242,7 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { impid: bidRequest.adUnitCode, transactionid: bidRequest.transactionId, auctionId: bidRequest.auctionId, - sizes: bidRequest.sizes.map(size => size[0] + 'x' + size[1]), + sizes: getBannerSizes(bidRequest), }; if (bidRequest.params.zoneId) { slot.zoneid = bidRequest.params.zoneId; @@ -236,6 +253,23 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (bidRequest.params.nativeCallback) { slot.native = true; } + if (hasVideoMediaType(bidRequest)) { + const video = { + playersizes: getVideoSizes(bidRequest), + mimes: bidRequest.mediaTypes.video.mimes, + protocols: bidRequest.mediaTypes.video.protocols, + maxduration: bidRequest.mediaTypes.video.maxduration, + api: bidRequest.mediaTypes.video.api + } + + video.skip = bidRequest.params.video.skip; + video.placement = bidRequest.params.video.placement; + video.minduration = bidRequest.params.video.minduration; + video.playbackmethod = bidRequest.params.video.playbackmethod; + video.startdelay = bidRequest.params.video.startdelay; + + slot.video = video; + } return slot; }), }; @@ -262,6 +296,66 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { return request; } +function getVideoSizes(bidRequest) { + return parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize')); +} + +function getBannerSizes(bidRequest) { + return parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes); +} + +function parseSize(size) { + return size[0] + 'x' + size[1]; +} + +function parseSizes(sizes) { + if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]]) + return sizes.map(size => parseSize(size)); + } + + return [parseSize(sizes)]; // or a single one ? (ie. [728,90]) +} + +function hasVideoMediaType(bidRequest) { + if (utils.deepAccess(bidRequest, 'params.video') === undefined) { + return false; + } + return utils.deepAccess(bidRequest, 'mediaTypes.video') !== undefined; +} + +function hasValidVideoMediaType(bidRequest) { + let isValid = true; + + var requiredMediaTypesParams = ['mimes', 'playerSize', 'maxduration', 'protocols', 'api']; + + requiredMediaTypesParams.forEach(function(param) { + if (utils.deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined) { + isValid = false; + utils.logError('Criteo Bid Adapter: mediaTypes.video.' + param + ' is required'); + } + }); + + var requiredParams = ['skip', 'placement', 'playbackmethod']; + + requiredParams.forEach(function(param) { + if (utils.deepAccess(bidRequest, 'params.video.' + param) === undefined) { + isValid = false; + utils.logError('Criteo Bid Adapter: params.video.' + param + ' is required'); + } + }); + + if (isValid) { + // We do not support long form for now, also we have to check that context & placement are consistent + if (bidRequest.mediaTypes.video.context == 'instream' && bidRequest.params.video.placement === 1) { + return true; + } else if (bidRequest.mediaTypes.video.context == 'outstream' && bidRequest.params.video.placement !== 1) { + return true; + } + } + + return false; +} + /** * @param {string} id * @param {*} payload diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index ac9ae53af07..4fe60bba17c 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -4,6 +4,7 @@ import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; import { config } from '../../../src/config'; +import { VIDEO } from '../../../src/mediaTypes'; describe('The Criteo bidding adapter', function () { beforeEach(function () { @@ -53,6 +54,309 @@ describe('The Criteo bidding adapter', function () { const isValid = spec.isBidRequestValid(bid); expect(isValid).to.equal(true); }); + + it('should return true when given a valid video bid request', function () { + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(true); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'outstream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 2, + playbackmethod: 1 + } + }, + })).to.equal(true); + }); + + it('should return false when given an invalid video bid request', function () { + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 2, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'outstream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'adpod', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30 + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + placement: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + playbackmethod: 1 + } + }, + })).to.equal(false); + + expect(spec.isBidRequestValid({ + bidder: 'criteo', + mediaTypes: { + video: { + context: 'instream', + mimes: ['video/mpeg'], + playerSize: [640, 480], + protocols: [5, 6], + maxduration: 30, + api: [1, 2] + } + }, + params: { + networkId: 456, + video: { + skip: 1, + placement: 1 + } + }, + })).to.equal(false); + }); }); describe('buildRequests', function () { @@ -118,7 +422,11 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', adUnitCode: 'bid-123', transactionId: 'transaction-123', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, params: { networkId: 456, }, @@ -205,6 +513,94 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.gdprConsent.consentGiven).to.equal(undefined); }); + it('should properly build a video request', function () { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + mediaTypes: { + video: { + playerSize: [640, 480], + mimes: ['video/mp4', 'video/x-flv'], + maxduration: 30, + api: [1, 2], + protocols: [2, 3] + } + }, + params: { + zoneId: 123, + video: { + skip: 1, + minduration: 5, + startdelay: 5, + playbackmethod: [1, 3], + placement: 2 + } + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest.slots[0].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); + expect(ortbRequest.slots[0].video.playersizes).to.deep.equal(['640x480']); + expect(ortbRequest.slots[0].video.maxduration).to.equal(30); + expect(ortbRequest.slots[0].video.api).to.deep.equal([1, 2]); + expect(ortbRequest.slots[0].video.protocols).to.deep.equal([2, 3]); + expect(ortbRequest.slots[0].video.skip).to.equal(1); + expect(ortbRequest.slots[0].video.minduration).to.equal(5); + expect(ortbRequest.slots[0].video.startdelay).to.equal(5); + expect(ortbRequest.slots[0].video.playbackmethod).to.deep.equal([1, 3]); + expect(ortbRequest.slots[0].video.placement).to.equal(2); + }); + + it('should properly build a video request with more than one player size', function () { + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + mediaTypes: { + video: { + playerSize: [[640, 480], [800, 600]], + mimes: ['video/mp4', 'video/x-flv'], + maxduration: 30, + api: [1, 2], + protocols: [2, 3] + } + }, + params: { + zoneId: 123, + video: { + skip: 1, + minduration: 5, + startdelay: 5, + playbackmethod: [1, 3], + placement: 2 + } + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + expect(request.method).to.equal('POST'); + const ortbRequest = request.data; + expect(ortbRequest.slots[0].video.mimes).to.deep.equal(['video/mp4', 'video/x-flv']); + expect(ortbRequest.slots[0].video.playersizes).to.deep.equal(['640x480', '800x600']); + expect(ortbRequest.slots[0].video.maxduration).to.equal(30); + expect(ortbRequest.slots[0].video.api).to.deep.equal([1, 2]); + expect(ortbRequest.slots[0].video.protocols).to.deep.equal([2, 3]); + expect(ortbRequest.slots[0].video.skip).to.equal(1); + expect(ortbRequest.slots[0].video.minduration).to.equal(5); + expect(ortbRequest.slots[0].video.startdelay).to.equal(5); + expect(ortbRequest.slots[0].video.playbackmethod).to.deep.equal([1, 3]); + expect(ortbRequest.slots[0].video.placement).to.equal(2); + }); + it('should properly build a request with ceh', function () { const bidRequests = [ { @@ -299,6 +695,39 @@ describe('The Criteo bidding adapter', function () { expect(bids[0].height).to.equal(90); }); + it('should properly parse a bid responsewith with a video', function () { + const response = { + body: { + slots: [{ + impid: 'test-requestId', + bidId: 'abc123', + cpm: 1.23, + displayurl: 'http://test-ad', + width: 728, + height: 90, + zoneid: 123, + video: true + }], + }, + }; + const request = { + bidRequests: [{ + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + zoneId: 123, + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('test-bidId'); + expect(bids[0].adId).to.equal('abc123'); + expect(bids[0].cpm).to.equal(1.23); + expect(bids[0].vastUrl).to.equal('http://test-ad'); + expect(bids[0].mediaType).to.equal(VIDEO); + }); + it('should properly parse a bid responsewith with a zoneId passed as a string', function () { const response = { body: { From 090cddab6783c67baf3d6a4bb231fa65ce56377c Mon Sep 17 00:00:00 2001 From: Unnamalai57 <49053809+Unnamalai57@users.noreply.github.com> Date: Tue, 6 Aug 2019 22:19:59 +0530 Subject: [PATCH 138/436] topRTBBidAdapter (#3817) * toprtbBidAdapter * topRTB adapter hbid queryparam added * toprtbBidAdapter-ssp aws url * topRTBBidAdapter * Video format topRTBBidAdapter * Video format topRTBBidAdapter * deviceType added * tracking new added * impression event added * fix test failed * fix testing failed * removed debug logs * added single quotes in adUnitId * remove console log * code committed to add SSL * adunitId changes for valid response --- modules/topRTBBidAdapter.js | 65 +++++++++++++++++++++ modules/topRTBBidAdapter.md | 30 ++++++++++ test/spec/modules/topRTBBidAdapter_spec.js | 67 ++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 modules/topRTBBidAdapter.js create mode 100644 modules/topRTBBidAdapter.md create mode 100644 test/spec/modules/topRTBBidAdapter_spec.js diff --git a/modules/topRTBBidAdapter.js b/modules/topRTBBidAdapter.js new file mode 100644 index 00000000000..783d4008b33 --- /dev/null +++ b/modules/topRTBBidAdapter.js @@ -0,0 +1,65 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; + +const BIDDER_CODE = 'topRTB'; +const ENDPOINT_URL = 'https://ssp.toprtb.com/ssp/rest/ReqAd?ref=www.google.com&hbid=0&adUnitId='; +var adName = ''; +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + isBidRequestValid: function (bid) { + if (utils.deepAccess(bid, 'mediaTypes.banner')) { + adName = 'banner'; + return bid.params && !!bid.params.adUnitId; + } + if (utils.deepAccess(bid, 'mediaTypes.video')) { + adName = 'video'; + return bid.params && !!bid.params.adUnitId; + } + }, + + buildRequests: function (validBidRequests, bidderRequest) { + let adunitid = []; + utils._each(validBidRequests, function (bid) { + adunitid.push(bid.params.adUnitId + '_' + bid.bidId); + }); + + return { + method: 'GET', + url: ENDPOINT_URL + adunitid.toString() + }; + }, + + interpretResponse: function(serverResponses, request) { + const bidResponses = []; + utils._each(serverResponses.body, function(response) { + if (response.cpm > 0) { + const bidResponse = { + requestId: response.bidId, + cpm: response.cpm, + width: response.width, + height: response.height, + ad: response.mediadata, + ttl: response.ttl, + creativeId: response.id, + netRevenue: true, + currency: response.currency, + tracking: response.tracking, + impression: response.impression + }; + if (adName == 'video') { + bidResponse.vastXml = response.mediadata; + bidResponse.mediaType = 'video'; + } else { + bidResponse.ad = response.mediadata; + bidResponse.mediaType = 'banner'; + } + bidResponses.push(bidResponse); + } + }); + return bidResponses; + } +}; + +registerBidder(spec); diff --git a/modules/topRTBBidAdapter.md b/modules/topRTBBidAdapter.md new file mode 100644 index 00000000000..d1930c928e4 --- /dev/null +++ b/modules/topRTBBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +``` +Module Name: topRTB Bidder Adapter +Module Type: Bidder Adapter +Maintainer: karthikeyan.d@djaxtech.com +``` + +# Description + +topRTB Bidder Adapter for Prebid.js. +Only Banner & video format is supported. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div-0', + sizes: [[728, 90]], // a display size + bids: [ + { + bidder: 'topRTB', + params: { + adUnitId: 'c5c06f77430c4c33814a0577cb4cc978' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/topRTBBidAdapter_spec.js b/test/spec/modules/topRTBBidAdapter_spec.js new file mode 100644 index 00000000000..83e5de3e4b9 --- /dev/null +++ b/test/spec/modules/topRTBBidAdapter_spec.js @@ -0,0 +1,67 @@ +import { expect } from 'chai'; +import { spec } from 'modules/topRTBBidAdapter'; + +describe('topRTBBidAdapterTests', function () { + it('validate_pub_params', function () { + expect(spec.isBidRequestValid({ + bidder: 'topRTB', + params: { + adUnitId: 'c5c06f77430c4c33814a0577cb4cc978' + }, + adName: 'banner' + })); + }); + + it('validate_generated_params', function () { + let bidRequestData = [{ + bidId: 'bid12345', + bidder: 'topRTB', + adName: 'banner', + adType: '{"banner":{"sizes":[[]]}}', + params: { + adUnitId: 'c5c06f77430c4c33814a0577cb4cc978' + }, + sizes: [[728, 90]] + }]; + + let request = spec.buildRequests(bidRequestData); + const current_url = request.url; + const search_params = current_url.searchParams; + }); + + it('validate_response_params', function () { + let bidRequestData = { + data: { + bidId: 'bid12345' + } + }; + + let serverResponse = { + body: [{ + 'cpm': 1, + 'mediadata': "Banner 728x90", + 'width': 728, + 'currency': 'USD', + 'id': 'cd95dffec6b645afbc4e5aa9f68f2ff3', + 'type': 'RICHMEDIA', + 'ttl': 4000, + 'bidId': 'bid12345', + 'status': 'success', + 'height': 90}], + 'adName': 'banner', + 'vastXml': '', + 'mediaType': 'banner', + 'tracking': 'https://ssp.toprtb.com/ssp/tracking?F0cloTiKIw%2BjZ2UNDvlKGn5%2FWoAO9cnlAUDm6gFBM8bImY2fKo%2BMTvI0XvXzFTZSb5v8o4EUbPId9hckptTqA4QPaWvpVYCRKRZceXNa4kjtvfm4j2e%2FcRKgkns2goHXi7IZC0sBIbE77WWg%2BPBYv%2BCu84H%2FSH69mi%2FDaWcQlfaEOdkaJdstJEkaZtkgWnFnS7aagte%2BfdEbOqcTxq5hzj%2BZ4NZbwgReuWTQZbfrMWjkXFbn%2B35vZuI319o6XH9n9fKLS4xp8zstXfQT2oSgjw1NmrwqRKf1efB1UaWlS1TbkSqxZ7Kcy7nJvAZrDk0tzcSeIxe4VfHpwgPPs%2BueUeGwz3o7OCh7H1sCmogSrmJFB9JTeXudFjC13iANAtu4SvG9bGIbiJxS%2BNfkjy2mLFm8kSIcIobjNkMEcUAwmoqJNRndwb66a3Iovk2NTo0Ly%2FV7Y5ECPcS5%2FPBrIEOuQXS5SNUPRWKoklX5nexHtOc%3D', + 'impression': 'https://ssp.toprtb.com/ssp/impression?id=64f29f7b226249f19925a680a506b32d' + }; + + let bids = spec.interpretResponse(serverResponse, bidRequestData); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(1); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(728); + expect(bid.height).to.equal(90); + expect(bid.requestId).to.equal('bid12345'); + }); +}); From d9fa4672ab85cec0bdfa0c66fa0ef8af48dd3a09 Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 6 Aug 2019 22:21:36 +0530 Subject: [PATCH 139/436] add check to see if adObject is present (#4058) --- src/secureCreatives.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index f8ba9477b52..df7abe4ebee 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -31,7 +31,7 @@ function receiveMessage(ev) { return bid.adId === data.adId; }); - if (data.message === 'Prebid Request') { + if (adObject && data.message === 'Prebid Request') { _sendAdToCreative(adObject, data.adServerDomain, ev.source); // save winning bids @@ -45,7 +45,7 @@ function receiveMessage(ev) { // message: 'Prebid Native', // adId: '%%PATTERN:hb_adid%%' // }), '*'); - if (data.message === 'Prebid Native') { + if (adObject && data.message === 'Prebid Native') { if (data.action === 'assetRequest') { const message = getAssetMessage(data, adObject); ev.source.postMessage(JSON.stringify(message), ev.origin); From 71b78f5777707fee4a618f5e6fa1ea5b39c6b39b Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Tue, 6 Aug 2019 20:00:21 +0200 Subject: [PATCH 140/436] Consent String added to the HB request (#4044) * nanointeractive bid adapter * nanointeractive bid adapter * - using utils.getParameterByName instead of utils.getTopWindowLocation().href - bidderCode is removed - Default ALG changed to 'ihr' - added protocol to 'cors' param * markdown file * enabling localhost for bid requests * Bugfix interpretResponse - added body; Removed unnecessary parameters; Adjusted tests; * New feature - subId * Fixed lint errors * Nano Interactive Bid Adapter New Bid params: - categoryName - name Getting referrer information * Fixed documentation * Removed unnecessary parameter from documentation * Cleaning up documentation * - Sending window location to server if possible * - Lint errors fix * Using utils.js method for sending location to server * Removing unnecessary parameter passing * added ConsentString to HB request * removing unused location params in testing --- modules/nanointeractiveBidAdapter.js | 93 +++++++--- .../modules/nanointeractiveBidAdapter_spec.js | 164 +++++------------- 2 files changed, 112 insertions(+), 145 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index cfef32b4c80..a76cc90ac10 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -1,11 +1,11 @@ import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER } from '../src/mediaTypes'; +import {config} from '../src/config'; +import {registerBidder} from '../src/adapters/bidderFactory'; export const BIDDER_CODE = 'nanointeractive'; -export const ENGINE_BASE_URL = 'https://www.audiencemanager.de/hb'; +export const END_POINT_URL = 'https://ad.audiencemanager.de'; -export const DATA_PARTNER_PIXEL_ID = 'pid'; +export const SSP_PLACEMENT_ID = 'pid'; export const NQ = 'nq'; export const NQ_NAME = 'name'; export const CATEGORY = 'category'; @@ -17,22 +17,27 @@ export const LOCATION = 'loc'; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [BANNER], + aliases: ['ni'], - isBidRequestValid (bid) { - const pid = bid.params[DATA_PARTNER_PIXEL_ID]; + isBidRequestValid(bid) { + const pid = bid.params[SSP_PLACEMENT_ID]; return !!(pid); }, - buildRequests (bidRequests) { + + buildRequests(validBidRequests, bidderRequest) { let payload = []; - bidRequests.forEach(bid => payload.push(createSingleBidRequest(bid))); + validBidRequests.forEach( + bid => payload.push(createSingleBidRequest(bid, bidderRequest)) + ); + const url = getEndpointUrl('main') + '/hb'; + return { method: 'POST', - url: ENGINE_BASE_URL, + url: url, data: JSON.stringify(payload) }; }, - interpretResponse (serverResponse) { + interpretResponse(serverResponse) { const bids = []; serverResponse.body.forEach(serverBid => { if (isEngineResponseValid(serverBid)) { @@ -41,23 +46,37 @@ export const spec = { }); return bids; } + }; -function createSingleBidRequest (bid) { - return { - [DATA_PARTNER_PIXEL_ID]: bid.params[DATA_PARTNER_PIXEL_ID], +function createSingleBidRequest(bid, bidderRequest) { + const location = utils.deepAccess(bidderRequest, 'refererInfo.referer'); + const origin = utils.getOrigin(); + const data = { + [SSP_PLACEMENT_ID]: bid.params[SSP_PLACEMENT_ID], [NQ]: [createNqParam(bid)], [CATEGORY]: [createCategoryParam(bid)], [SUB_ID]: createSubIdParam(bid), - [REF]: createRefParam(bid), + [REF]: createRefParam(), sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, - cors: utils.getOrigin(), - [LOCATION]: createLocationParam(), + cors: origin, + [LOCATION]: location, + lsUserId: getLsUserId() }; + + if (bidderRequest && bidderRequest.gdprConsent) { + data['gdprConsent'] = bidderRequest.gdprConsent.consentString; + data['gdprApplies'] = (bidderRequest.gdprConsent.gdprApplies) ? '1' : '0'; + } + + return data; } -function createSingleBidResponse (serverBid) { +function createSingleBidResponse(serverBid) { + if (serverBid.userId) { + localStorage.setItem('lsUserId', serverBid.userId); + } return { requestId: serverBid.id, cpm: serverBid.cpm, @@ -67,32 +86,50 @@ function createSingleBidResponse (serverBid) { ttl: serverBid.ttl, creativeId: serverBid.creativeId, netRevenue: serverBid.netRevenue || true, - currency: serverBid.currency, + currency: serverBid.currency }; } -function createNqParam (bid) { +function createNqParam(bid) { return bid.params[NQ_NAME] ? utils.getParameterByName(bid.params[NQ_NAME]) : bid.params[NQ] || null; } -function createCategoryParam (bid) { +function createCategoryParam(bid) { return bid.params[CATEGORY_NAME] ? utils.getParameterByName(bid.params[CATEGORY_NAME]) : bid.params[CATEGORY] || null; } -function createSubIdParam (bid) { +function createSubIdParam(bid) { return bid.params[SUB_ID] || null; } -function createRefParam (bid) { - return bid.params[REF] ? null : utils.getTopWindowReferrer() || null; +function createRefParam() { + try { + return window.top.document.referrer; + } catch (ex) { + return document.referrer; + } } -function createLocationParam () { - return utils.getTopWindowLocation().href; +function isEngineResponseValid(response) { + return !!response.cpm && !!response.ad; } -function isEngineResponseValid (response) { - return !!response.cpm && !!response.ad; +/** + * Used mainly for debugging + * + * @param type + * @returns string + */ +function getEndpointUrl(type) { + const nanoConfig = config.getConfig('nano'); + return (nanoConfig && nanoConfig['endpointUrl']) || END_POINT_URL; +} + +function getLsUserId() { + if (localStorage.getItem('lsUserId') != null) { + return localStorage.getItem('lsUserId'); + } + return null; } registerBidder(spec); diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 3731535b88a..a357327fe96 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -1,4 +1,4 @@ -import { expect } from 'chai'; +import {expect} from 'chai'; import * as utils from 'src/utils'; import * as sinon from 'sinon'; @@ -6,8 +6,8 @@ import { BIDDER_CODE, CATEGORY, CATEGORY_NAME, - DATA_PARTNER_PIXEL_ID, - ENGINE_BASE_URL, + SSP_PLACEMENT_ID, + END_POINT_URL, NQ, NQ_NAME, REF, @@ -19,8 +19,6 @@ describe('nanointeractive adapter tests', function () { const SIZES_PARAM = 'sizes'; const BID_ID_PARAM = 'bidId'; const BID_ID_VALUE = '24a1c9ec270973'; - const CORS_PARAM = 'cors'; - const LOC_PARAM = 'loc'; const DATA_PARTNER_PIXEL_ID_VALUE = 'testPID'; const NQ_VALUE = 'rumpelstiltskin'; const NQ_NAME_QUERY_PARAM = 'nqName'; @@ -37,21 +35,7 @@ describe('nanointeractive adapter tests', function () { const AD = ' '; const CPM = 1; - function getBidResponse (pid, nq, category, subId, cors, ref, loc) { - return { - [DATA_PARTNER_PIXEL_ID]: pid, - [NQ]: nq, - [CATEGORY]: category, - [SUB_ID]: subId, - [REF]: ref, - [SIZES_PARAM]: [WIDTH1 + 'x' + HEIGHT1, WIDTH2 + 'x' + HEIGHT2], - [BID_ID_PARAM]: BID_ID_VALUE, - [CORS_PARAM]: cors, - [LOC_PARAM]: loc, - }; - } - - function getBidRequest (params) { + function getBidRequest(params) { return { bidder: BIDDER_CODE, params: params, @@ -70,85 +54,85 @@ describe('nanointeractive adapter tests', function () { describe('Methods', function () { it('Test isBidRequestValid() with valid param(s): pid', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, category', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, [CATEGORY]: CATEGORY_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, categoryName', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName, category', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY]: CATEGORY_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nqName, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, category', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, category, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [SUB_ID]: SUB_ID_VALUE, }))).to.equal(true); }); it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -156,7 +140,7 @@ describe('nanointeractive adapter tests', function () { }); it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName, subId', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, [SUB_ID]: SUB_ID_VALUE, @@ -164,7 +148,7 @@ describe('nanointeractive adapter tests', function () { }); it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value none)', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -173,7 +157,7 @@ describe('nanointeractive adapter tests', function () { }); it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value other)', function () { expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -193,30 +177,22 @@ describe('nanointeractive adapter tests', function () { let sandbox; - function getMocks () { - let mockWindowLocationAddress = 'http://some-location.test'; + function getMocks() { let mockOriginAddress = 'http://localhost'; let mockRefAddress = 'http://some-ref.test'; return { - 'windowLocationAddress': mockWindowLocationAddress, + 'windowLocationAddress': mockRefAddress, 'originAddress': mockOriginAddress, - 'refAddress': mockRefAddress, + 'refAddress': '', }; } - function setUpMocks (mockRefAddress = null) { + function setUpMocks() { + sinon.sandbox.restore(); sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'getOrigin').callsFake(() => getMocks()['originAddress']); - sandbox.stub(utils, 'getTopWindowLocation').callsFake(() => { - return { - 'href': getMocks()['windowLocationAddress'] - }; - }); - if (mockRefAddress == null) { - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => getMocks()['refAddress']); - } else { - sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); - } + sandbox.stub(utils, 'deepAccess').callsFake(() => getMocks()['windowLocationAddress']); + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { switch (arg) { case CATEGORY_NAME_QUERY_PARAM: @@ -227,39 +203,31 @@ describe('nanointeractive adapter tests', function () { }); } - function assert ( + function assert( request, expectedPid, expectedNq, expectedCategory, - expectedSubId, - expectedRef = getMocks()['refAddress'], - expectedOrigin = getMocks()['originAddress'], - expectedLocation = getMocks()['windowLocationAddress'] + expectedSubId ) { + const requestData = JSON.parse(request.data); + expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([ - getBidResponse( - expectedPid, - expectedNq, - expectedCategory, - expectedSubId, - expectedOrigin, - expectedRef, - expectedLocation, - ), - ])); + expect(request.url).to.equal(END_POINT_URL + '/hb'); + expect(requestData[0].pid).to.equal(expectedPid); + expect(requestData[0].nq.toString()).to.equal(expectedNq.toString()); + expect(requestData[0].category.toString()).to.equal(expectedCategory.toString()); + expect(requestData[0].subId).to.equal(expectedSubId); } - function tearDownMocks () { + function tearDownMocks() { sandbox.restore(); } it('Test buildRequest() - pid', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; let expectedNq = [null]; @@ -274,7 +242,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; @@ -290,7 +258,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq, category', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, }; @@ -308,7 +276,7 @@ describe('nanointeractive adapter tests', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, }; @@ -325,7 +293,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [SUB_ID]: SUB_ID_VALUE, }; @@ -342,7 +310,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, category', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; @@ -358,7 +326,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, category, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, }; @@ -375,7 +343,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [SUB_ID]: SUB_ID_VALUE, }; let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; @@ -391,7 +359,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nq, category, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ]: NQ_VALUE, [CATEGORY]: CATEGORY_VALUE, [SUB_ID]: SUB_ID_VALUE, @@ -409,7 +377,7 @@ describe('nanointeractive adapter tests', function () { it('Test buildRequest() - pid, nqName, categoryName, subId', function () { setUpMocks(); let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SSP_PLACEMENT_ID]: DATA_PARTNER_PIXEL_ID_VALUE, [NQ_NAME]: NQ_NAME_QUERY_PARAM, [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, [SUB_ID]: SUB_ID_VALUE, @@ -424,44 +392,6 @@ describe('nanointeractive adapter tests', function () { assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); tearDownMocks(); }); - it('Test buildRequest() - pid, nq, category, subId, ref (value none)', function () { - setUpMocks(null); - let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - [REF]: REF_NO_VALUE, - }; - let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; - let expectedNq = [NQ_VALUE]; - let expectedCategory = [CATEGORY_VALUE]; - let expectedSubId = SUB_ID_VALUE; - - let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); - - assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); - tearDownMocks(); - }); - it('Test buildRequest() - pid, nq, category, subId, ref (value other)', function () { - setUpMocks(null); - let requestParams = { - [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, - [NQ]: NQ_VALUE, - [CATEGORY]: CATEGORY_VALUE, - [SUB_ID]: SUB_ID_VALUE, - [REF]: REF_OTHER_VALUE, - }; - let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; - let expectedNq = [NQ_VALUE]; - let expectedCategory = [CATEGORY_VALUE]; - let expectedSubId = SUB_ID_VALUE; - - let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); - - assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); - tearDownMocks(); - }); it('Test interpretResponse() length', function () { let bids = nanoBidAdapter.interpretResponse({ body: [ From 408898a0070dbb54f801cee9672ed4ef7f0fce98 Mon Sep 17 00:00:00 2001 From: Andy Day Date: Tue, 6 Aug 2019 11:28:28 -0700 Subject: [PATCH 141/436] Update URI for IdentityLink integration (#4049) * Update URI for IdentityLink integration We have moved the URI for the Envelope API, and are currently shiming requests with the rt parameter. This will eventually be deprecated, so we want to update to the correct URI w/o the rt param. * bump --- modules/identityLinkSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/identityLinkSystem.js b/modules/identityLinkSystem.js index 8b8fa491bad..ef916252811 100644 --- a/modules/identityLinkSystem.js +++ b/modules/identityLinkSystem.js @@ -37,7 +37,7 @@ export const identityLinkSubmodule = { return; } // use protocol relative urls for http or https - const url = `https://api.rlcdn.com/api/identity?pid=${configParams.pid}&rt=envelope`; + const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}`; return function (callback) { ajax(url, response => { From 30a90ef33be3b2f869c58bfb7c63abedd69cac6a Mon Sep 17 00:00:00 2001 From: Jurij Sinickij Date: Tue, 6 Aug 2019 21:43:08 +0300 Subject: [PATCH 142/436] adformOpenRTB adapter: parse seatbid bid responses (#4043) --- modules/adformOpenRTBBidAdapter.js | 8 +- .../modules/adformOpenRTBBidAdapter_spec.js | 73 ++++++++++++++++++- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/modules/adformOpenRTBBidAdapter.js b/modules/adformOpenRTBBidAdapter.js index 0f69ccd6262..98e6de8036a 100644 --- a/modules/adformOpenRTBBidAdapter.js +++ b/modules/adformOpenRTBBidAdapter.js @@ -143,9 +143,13 @@ export const spec = { } const { seatbid, cur } = serverResponse.body; + const bidResponses = flatten(seatbid.map(seat => seat.bid)).reduce((result, bid) => { + result[bid.impid - 1] = bid; + return result; + }, []); + return bids.map((bid, id) => { - const _cbid = seatbid && seatbid[id] && seatbid[id].bid; - const bidResponse = _cbid && _cbid[0]; + const bidResponse = bidResponses[id]; if (bidResponse) { return { requestId: bid.bidId, diff --git a/test/spec/modules/adformOpenRTBBidAdapter_spec.js b/test/spec/modules/adformOpenRTBBidAdapter_spec.js index cafbe4eff15..32795c24ef6 100644 --- a/test/spec/modules/adformOpenRTBBidAdapter_spec.js +++ b/test/spec/modules/adformOpenRTBBidAdapter_spec.js @@ -384,9 +384,9 @@ describe('AdformOpenRTB adapter', function () { let serverResponse = { body: { seatbid: [{ - bid: [{impid: 'impid1', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}] + bid: [{impid: '1', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}] }, { - bid: [{impid: 'impid2', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] + bid: [{impid: '2', native: {ver: '1.1', link: { url: 'link' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] }] } }; @@ -417,6 +417,71 @@ describe('AdformOpenRTB adapter', function () { bids = spec.interpretResponse(serverResponse, bidRequest); assert.equal(spec.interpretResponse(serverResponse, bidRequest).length, 2); }); + + it('should parse seatbids', function () { + let serverResponse = { + body: { + seatbid: [{ + bid: [ + {impid: '1', native: {ver: '1.1', link: { url: 'link1' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}}, + {impid: '4', native: {ver: '1.1', link: { url: 'link4' }, assets: [{id: 1, title: {text: 'Asset title text'}}]}} + ] + }, { + bid: [{impid: '2', native: {ver: '1.1', link: { url: 'link2' }, assets: [{id: 1, data: {value: 'Asset title text'}}]}}] + }] + } + }; + let bidRequest = { + data: {}, + bids: [ + { + bidId: 'bidId1', + params: { siteId: 'siteId', mid: 1000 }, + nativeParams: { + title: { required: true, len: 140 }, + image: { required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif'] }, + body: { len: 140 } + } + }, + { + bidId: 'bidId2', + params: { siteId: 'siteId', mid: 1000 }, + nativeParams: { + title: { required: true, len: 140 }, + image: { required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif'] }, + body: { len: 140 } + } + }, + { + bidId: 'bidId3', + params: { siteId: 'siteId', mid: 1000 }, + nativeParams: { + title: { required: true, len: 140 }, + image: { required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif'] }, + body: { len: 140 } + } + }, + { + bidId: 'bidId4', + params: { siteId: 'siteId', mid: 1000 }, + nativeParams: { + title: { required: true, len: 140 }, + image: { required: false, wmin: 836, hmin: 627, w: 325, h: 300, mimes: ['image/jpg', 'image/gif'] }, + body: { len: 140 } + } + } + ] + }; + + bids = spec.interpretResponse(serverResponse, bidRequest).map(bid => { + const { requestId, native: { clickUrl } } = bid; + return [ requestId, clickUrl ]; + }); + + assert.equal(bids.length, 3); + assert.deepEqual(bids, [[ 'bidId1', 'link1' ], [ 'bidId2', 'link2' ], [ 'bidId4', 'link4' ]]); + }); + it('should set correct values to bid', function () { let serverResponse = { body: { @@ -425,7 +490,7 @@ describe('AdformOpenRTB adapter', function () { seatbid: [{ bid: [ { - impid: 'impid1', + impid: '1', price: 93.1231, crid: '12312312', native: { @@ -468,7 +533,7 @@ describe('AdformOpenRTB adapter', function () { it('should set correct native params', function () { const bid = [ { - impid: 'impid1', + impid: '1', price: 93.1231, crid: '12312312', native: { From cf63c27cbd2edc72910a2dd004aa5bbade764b76 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 6 Aug 2019 15:27:39 -0400 Subject: [PATCH 143/436] revert karma and other package updates (#4067) --- .circleci/config.yml | 2 +- README.md | 4 +- package-lock.json | 8591 +++++++++--------------------------------- package.json | 6 +- 4 files changed, 1735 insertions(+), 6868 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 85452b5aa88..16bdd5b317e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: build: docker: # specify the version you desire here - - image: circleci/node:9.0.0 + - image: circleci/node:7.10 # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images diff --git a/README.md b/README.md index a50c55f96ca..21e02ebee7f 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ module.exports = { } ``` -Or for Babel 6: +Or for Babel 6 and/or Node v8.6.0 and less: ```javascript // you must manually install and specify the presets and plugins yourself options: { @@ -112,7 +112,7 @@ prebid.requestBids({ $ cd Prebid.js $ npm install -*Note:* You need to have `NodeJS` 9.x or greater installed. +*Note:* You need to have `NodeJS` 6.x or greater installed. *Note:* In the 1.24.0 release of Prebid.js we have transitioned to using gulp 4.0 from using gulp 3.9.1. To compily with gulp's recommended setup for 4.0, you'll need to have `gulp-cli` installed globally prior to running the general `npm install`. This shouldn't impact any other projects you may work on that use an earlier version of gulp in it's setup. diff --git a/package-lock.json b/package-lock.json index 1ed87be2492..e8e1461cbe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,172 +2,96 @@ "name": "prebid.js", "version": "2.27.0-pre", "lockfileVersion": 1, - "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true }, "@babel/core": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", - "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helpers": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.5", - "@babel/types": "^7.4.4", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.11", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "dev": true }, "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true }, "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-call-delegate": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/helper-define-map": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "dev": true }, "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-hoist-variables": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "dev": true }, "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-module-transforms": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.4.4", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "dev": true }, "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-plugin-utils": { "version": "7.0.0", @@ -176,607 +100,346 @@ "dev": true }, "@babel/helper-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "dev": true }, "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-replace-supers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "dev": true }, "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } + "dev": true }, "@babel/helper-split-export-declaration": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" - } + "dev": true }, "@babel/helpers": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", - "dev": true, - "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "dev": true }, "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true }, "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" - } + "dev": true + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "dev": true }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" - } + "dev": true }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", + "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "dev": true }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" - } + "dev": true }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "dev": true }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-syntax-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-async-to-generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "dev": true }, "@babel/plugin-transform-block-scoped-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-block-scoping": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", + "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", + "dev": true }, "@babel/plugin-transform-classes": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.4.4", - "@babel/helper-split-export-declaration": "^7.4.4", - "globals": "^11.1.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "dev": true }, "@babel/plugin-transform-computed-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-destructuring": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", + "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", + "dev": true }, "@babel/plugin-transform-dotall-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } + "dev": true }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "dev": true }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-for-of": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-function-name": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-member-expression-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-modules-amd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "dev": true }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", + "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", + "dev": true }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0" - } + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "dev": true }, "@babel/plugin-transform-modules-umd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", - "dev": true, - "requires": { - "regexp-tree": "^0.1.6" - } + "dev": true }, "@babel/plugin-transform-new-target": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-object-super": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "dev": true }, "@babel/plugin-transform-parameters": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-property-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-regenerator": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.0" - } + "dev": true }, "@babel/plugin-transform-reserved-words": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-spread": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-sticky-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-template-literals": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-typeof-symbol": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "dev": true }, "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } + "dev": true }, "@babel/preset-env": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.5.tgz", - "integrity": "sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.4.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.4.4", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.4.4", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-modules-systemjs": "^7.4.4", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", + "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "dev": true }, "@babel/template": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } + "dev": true }, "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true }, "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true }, "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", "dev": true, - "requires": { - "acorn": "^5.0.3", - "css": "^2.2.1", - "normalize-path": "^2.1.1", - "source-map": "^0.6.0", - "through2": "^2.0.3" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true }, "source-map": { "version": "0.6.1", @@ -791,19 +454,12 @@ "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", "dev": true, - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true } } }, @@ -817,38 +473,19 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } + "dev": true }, "@sinonjs/formatio": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true, - "requires": { - "samsam": "1.3.0" - }, - "dependencies": { - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - } - } + "dev": true }, "@sinonjs/samsam": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.0.2", - "array-from": "^2.1.1", - "lodash": "^4.17.11" - } + "dev": true }, "@sinonjs/text-encoding": { "version": "0.7.1", @@ -856,219 +493,17 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } + "dev": true }, "acorn": { "version": "5.7.3", @@ -1081,9 +516,6 @@ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, - "requires": { - "acorn": "^4.0.3" - }, "dependencies": { "acorn": { "version": "4.0.13", @@ -1098,9 +530,6 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, - "requires": { - "acorn": "^3.0.4" - }, "dependencies": { "acorn": { "version": "3.3.0", @@ -1111,9 +540,9 @@ } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, "after": { @@ -1126,27 +555,12 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } + "dev": true }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", "dev": true }, "ajv-keywords": { @@ -1160,20 +574,12 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -1181,8 +587,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true + "dev": true }, "ansi-colors": { "version": "3.2.3", @@ -1200,10 +605,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } + "dev": true }, "ansi-html": { "version": "0.0.7", @@ -1221,10 +623,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } + "dev": true }, "ansi-wrap": { "version": "0.1.0", @@ -1237,19 +636,12 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true } } }, @@ -1257,24 +649,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } + "dev": true }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "^1.0.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "archiver": { @@ -1282,25 +662,12 @@ "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "async": "^2.0.0", - "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^1.2.0" - }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true } } }, @@ -1309,23 +676,12 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", "dev": true, - "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", - "lazystream": "^1.0.0", - "lodash": "^4.8.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true } } }, @@ -1339,10 +695,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } + "dev": true }, "arr-diff": { "version": "4.0.0", @@ -1354,10 +707,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } + "dev": true }, "arr-flatten": { "version": "1.1.0", @@ -1369,10 +719,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } + "dev": true }, "arr-union": { "version": "3.1.0", @@ -1420,21 +767,13 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" - } + "dev": true }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -1449,9 +788,6 @@ "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, - "requires": { - "is-number": "^4.0.0" - }, "dependencies": { "is-number": { "version": "4.0.0", @@ -1484,11 +820,6 @@ "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -1520,31 +851,19 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } + "dev": true }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "dev": true }, "assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, "dependencies": { "inherits": { "version": "2.0.1", @@ -1556,10 +875,7 @@ "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } + "dev": true } } }, @@ -1591,13 +907,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } + "dev": true }, "async-each": { "version": "1.0.3", @@ -1606,19 +916,16 @@ "dev": true }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, "async-settle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } + "dev": true }, "asynckit": { "version": "0.4.0", @@ -1649,11 +956,6 @@ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -1665,14 +967,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } + "dev": true }, "js-tokens": { "version": "3.0.2", @@ -1693,36 +988,12 @@ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "json5": { "version": "0.5.1", @@ -1743,16 +1014,6 @@ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, "dependencies": { "jsesc": { "version": "1.3.0", @@ -1766,202 +1027,115 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } + "dev": true }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-loader": { "version": "8.0.6", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "dev": true, - "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" - } + "dev": true }, "babel-messages": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", @@ -2051,323 +1225,181 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0" - } + "dev": true }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "^6.18.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true, - "requires": { - "babel-plugin-syntax-decorators": "^6.1.18", - "babel-runtime": "^6.2.0", - "babel-template": "^6.3.0" - } + "dev": true }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } + "dev": true }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -2379,12 +1411,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } + "dev": true }, "regjsgen": { "version": "0.2.0", @@ -2396,10 +1423,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } + "dev": true } } }, @@ -2407,120 +1431,72 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-object-assign": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", - "requires": { - "babel-runtime": "^6.22.0" - } + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=" }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } + "dev": true }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } + "dev": true }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - }, "dependencies": { "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } + "dev": true } } }, @@ -2528,59 +1504,19 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "dev": true }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - }, "dependencies": { "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } + "dev": true } } }, @@ -2588,134 +1524,66 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } + "dev": true }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } + "dev": true }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "^6.22.0", - "babel-plugin-transform-function-bind": "^6.22.0", - "babel-preset-stage-1": "^6.24.1" - } + "dev": true }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "^6.24.1", - "babel-plugin-transform-export-extensions": "^6.22.0", - "babel-preset-stage-2": "^6.24.1" - } + "dev": true }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" - } + "dev": true }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" - } + "dev": true }, "babel-register": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } + "dev": true }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=" }, "babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } + "dev": true }, "babel-traverse": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "globals": { "version": "9.18.0", @@ -2736,12 +1604,6 @@ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, "dependencies": { "to-fast-properties": { "version": "1.0.3", @@ -2767,18 +1629,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } + "dev": true }, "backo2": { "version": "1.0.2", @@ -2803,53 +1654,30 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } + "dev": true }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "dev": true } } }, @@ -2860,9 +1688,9 @@ "dev": true }, "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, "base64id": { @@ -2881,10 +1709,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } + "dev": true }, "beeper": { "version": "1.1.1", @@ -2896,22 +1721,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } + "dev": true }, "bfj": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", - "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "check-types": "^7.3.0", - "hoopy": "^0.1.2", - "tryer": "^1.0.0" - } + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "dev": true }, "big.js": { "version": "5.2.2", @@ -2935,11 +1751,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } + "dev": true }, "blob": { "version": "0.0.5", @@ -2963,31 +1775,13 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } + "dev": true }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, "dependencies": { "bytes": { "version": "3.1.0", @@ -2999,23 +1793,19 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "ms": { "version": "2.0.0", @@ -3033,13 +1823,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } + "dev": true }, "setprototypeof": { "version": "1.1.1", @@ -3053,38 +1837,19 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "dev": true }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true } } }, @@ -3099,9 +1864,6 @@ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, - "requires": { - "resolve": "1.1.7" - }, "dependencies": { "resolve": { "version": "1.1.7", @@ -3121,139 +1883,67 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } + "dev": true }, "browserify-des": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "dev": true }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } + "dev": true }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } + "dev": true }, "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } + "dev": true }, "browserslist": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.3.tgz", - "integrity": "sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000975", - "electron-to-chromium": "^1.3.164", - "node-releases": "^1.1.23" - } + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", + "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "dev": true }, "browserstack": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1" - } + "dev": true }, "browserstack-local": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", - "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1", - "is-running": "^2.0.0", - "ps-tree": "=1.1.1", - "sinon": "^1.17.6", - "temp-fs": "^0.9.9" - }, - "dependencies": { - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" - } - } - } + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", + "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", + "dev": true }, "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } + "dev": true }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } + "dev": true }, "buffer-alloc-unsafe": { "version": "1.1.0", @@ -3309,85 +1999,17 @@ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", "dev": true }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } + "dev": true }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, - "requires": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - }, "dependencies": { "lowercase-keys": { "version": "1.0.0", @@ -3399,12 +2021,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - } + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -3414,23 +2031,15 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } + "dev": true }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } + "dev": true } } }, @@ -3438,10 +2047,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } + "dev": true }, "callsite": { "version": "1.0.0", @@ -3466,10 +2072,6 @@ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -3480,9 +2082,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000975", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000975.tgz", - "integrity": "sha512-ZsXA9YWQX6ATu5MNg+Vx/cMQ+hM6vBBSqDeJs8ruk9z0ky4yIHML15MoxcFt088ST2uyjgqyUGRJButkptWf0w==", + "version": "1.0.30000989", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", + "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==", "dev": true }, "caseless": { @@ -3501,36 +2103,19 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } + "dev": true }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } + "dev": true }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "dev": true }, "character-entities": { "version": "1.2.3", @@ -3569,55 +2154,22 @@ "dev": true }, "check-types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", - "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", + "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", "dev": true }, "chokidar": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", "dev": true }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "circular-json": { "version": "0.3.3", @@ -3630,21 +2182,12 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "dev": true } } }, @@ -3652,10 +2195,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } + "dev": true }, "cli-width": { "version": "2.2.0", @@ -3668,11 +2208,6 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -3684,10 +2219,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "dev": true } } }, @@ -3707,10 +2239,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "dev": true }, "clone-stats": { "version": "1.0.0", @@ -3722,12 +2251,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } + "dev": true }, "co": { "version": "4.6.0", @@ -3751,31 +2275,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } + "dev": true }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } + "dev": true }, "color-name": { "version": "1.1.3", @@ -3795,14 +2307,17 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } + "dev": true }, "comma-separated-tokens": { "version": "1.0.7", @@ -3845,21 +2360,12 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", "dev": true, - "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true } } }, @@ -3873,22 +2379,13 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } + "dev": true }, "concat-with-sourcemaps": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, - "requires": { - "source-map": "^0.6.1" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -3903,21 +2400,12 @@ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -3937,10 +2425,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } + "dev": true }, "constants-browserify": { "version": "1.0.0", @@ -3958,10 +2443,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } + "dev": true }, "content-type": { "version": "1.0.4", @@ -3979,10 +2461,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } + "dev": true }, "cookie": { "version": "0.3.1", @@ -3996,31 +2475,6 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4031,11 +2485,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } + "dev": true }, "core-js": { "version": "2.6.9", @@ -4047,16 +2497,11 @@ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", "dev": true, - "requires": { - "browserslist": "^4.6.2", - "core-js-pure": "3.1.4", - "semver": "^6.1.1" - }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -4074,106 +2519,52 @@ "dev": true }, "coveralls": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.4.tgz", - "integrity": "sha512-eyqUWA/7RT0JagiL0tThVhjbIjoiEUyWCjtUJoOPcWoeofP5WK/jb2OJYoBFrR6DvplR+AxOyuBqk4JHkk5ykA==", - "dev": true, - "requires": { - "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.86.0" - } + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", + "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", + "dev": true }, "crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "requires": { - "buffer": "^5.1.0" - } + "dev": true }, "crc32-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true, - "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" - } + "dev": true }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } + "dev": true }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } + "dev": true }, "create-hmac": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } + "dev": true }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } + "dev": true }, "crypto-js": { "version": "3.1.9-1", @@ -4185,12 +2576,6 @@ "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -4204,10 +2589,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true, - "requires": { - "css": "^2.0.0" - } + "dev": true }, "css-value": { "version": "0.0.1", @@ -4219,10 +2601,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } + "dev": true }, "custom-event": { "version": "1.0.1", @@ -4230,35 +2609,22 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } + "dev": true }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } + "dev": true }, "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "date-now": { @@ -4271,40 +2637,25 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } + "dev": true }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "debug-fabulous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", "dev": true, - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -4324,19 +2675,13 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "dev": true }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } + "dev": true }, "deep-is": { "version": "0.1.3", @@ -4355,9 +2700,6 @@ "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -4372,18 +2714,12 @@ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, - "requires": { - "strip-bom": "^2.0.0" - }, "dependencies": { "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "dev": true } } }, @@ -4397,49 +2733,31 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } + "dev": true }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "dev": true } } }, @@ -4465,11 +2783,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "dev": true }, "destroy": { "version": "1.0.4", @@ -4481,10 +2795,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.2.tgz", "integrity": "sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ==", - "dev": true, - "requires": { - "repeat-string": "^1.5.4" - } + "dev": true }, "detect-file": { "version": "1.0.0", @@ -4496,10 +2807,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } + "dev": true }, "detect-libc": { "version": "1.0.3", @@ -4517,11 +2825,7 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true, - "requires": { - "acorn": "^5.2.1", - "defined": "^1.0.0" - } + "dev": true }, "di": { "version": "0.0.1", @@ -4539,22 +2843,13 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } + "dev": true }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", "dev": true, - "requires": { - "ansi-styles": "^2.0.1", - "diff": "^1.3.2" - }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -4573,78 +2868,19 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "dev": true }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } + "dev": true }, "documentation": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, - "requires": { - "ansi-html": "^0.0.7", - "babel-core": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-plugin-system-import-transformer": "3.1.0", - "babel-plugin-transform-decorators-legacy": "^1.3.4", - "babel-preset-env": "^1.6.1", - "babel-preset-react": "^6.24.1", - "babel-preset-stage-0": "^6.24.1", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babelify": "^8.0.0", - "babylon": "^6.18.0", - "chalk": "^2.3.0", - "chokidar": "^2.0.0", - "concat-stream": "^1.6.0", - "disparity": "^2.0.0", - "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", - "get-port": "^3.2.0", - "git-url-parse": "^8.0.0", - "github-slugger": "1.2.0", - "glob": "^7.1.2", - "globals-docs": "^2.4.0", - "highlight.js": "^9.12.0", - "js-yaml": "^3.10.0", - "lodash": "^4.17.4", - "mdast-util-inject": "^1.1.0", - "micromatch": "^3.1.5", - "mime": "^1.4.1", - "module-deps-sortable": "4.0.6", - "parse-filepath": "^1.0.2", - "pify": "^3.0.0", - "read-pkg-up": "^3.0.0", - "remark": "^9.0.0", - "remark-html": "7.0.0", - "remark-reference-links": "^4.0.1", - "remark-toc": "^5.0.0", - "remote-origin-url": "0.4.0", - "shelljs": "^0.8.1", - "stream-array": "^1.1.2", - "strip-json-comments": "^2.0.1", - "tiny-lr": "^1.1.0", - "unist-builder": "^1.0.2", - "unist-util-visit": "^1.3.0", - "vfile": "^2.3.0", - "vfile-reporter": "^4.0.0", - "vfile-sort": "^2.1.0", - "vinyl": "^2.1.0", - "vinyl-fs": "^3.0.2", - "yargs": "^9.0.1" - }, "dependencies": { "camelcase": { "version": "4.1.0", @@ -4657,22 +2893,12 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, "dependencies": { "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true } } }, @@ -4680,36 +2906,19 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } + "dev": true }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "dev": true }, "get-caller-file": { "version": "1.0.3", @@ -4727,31 +2936,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "dev": true }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -4765,20 +2962,19 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } + "dev": true }, "mimic-fn": { "version": "1.2.0", @@ -4790,30 +2986,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } + "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } + "dev": true }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -4825,19 +3010,13 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } + "dev": true }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, - "requires": { - "pify": "^2.0.0" - }, "dependencies": { "pify": { "version": "2.3.0", @@ -4857,12 +3036,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "require-main-filename": { "version": "1.0.1", @@ -4876,36 +3050,23 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, - "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "read-pkg-up": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - }, "dependencies": { "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } + "dev": true } } }, @@ -4913,10 +3074,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } + "dev": true } } }, @@ -4924,13 +3082,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } + "dev": true }, "domain-browser": { "version": "1.2.0", @@ -4953,10 +3105,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } + "dev": true }, "duplexer3": { "version": "0.1.4", @@ -4968,33 +3117,19 @@ "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } + "dev": true }, "each-props": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } + "dev": true }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "dev": true }, "editions": { "version": "1.3.4", @@ -5015,25 +3150,16 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.164", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.164.tgz", - "integrity": "sha512-VLlalqUeduN4+fayVtRZvGP2Hl1WrRxlwzh2XVVMJym3IFrQUS29BFQ1GP/BxOJXJI1OFCrJ5BnFEsAe8NHtOg==", + "version": "1.3.215", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.215.tgz", + "integrity": "sha512-ZV3OnwF0FlIygwxAG2H92yt7WGjWBpawyFAFu8e9k7xJatY+BPowID0D0Bs3PMACYAJATEejw/I9cawO27ZvTg==", "dev": true }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "dev": true }, "emoji-regex": { "version": "7.0.3", @@ -5057,33 +3183,19 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } + "dev": true }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -5095,22 +3207,9 @@ }, "engine.io-client": { "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -5121,11 +3220,8 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -5139,26 +3235,13 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } + "dev": true }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "object-assign": "^4.0.1", - "tapable": "^0.2.7" - } + "dev": true }, "ent": { "version": "2.2.0", @@ -5170,65 +3253,37 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } + "dev": true }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, - "requires": { - "string-template": "~0.2.1", - "xtend": "~4.0.0" - } + "dev": true }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } + "dev": true }, "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - } + "dev": true }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } + "dev": true }, "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } + "dev": true }, "es5-shim": { "version": "4.5.13", @@ -5240,26 +3295,13 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } + "dev": true }, "es6-map": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } + "dev": true }, "es6-promise": { "version": "4.2.8", @@ -5271,45 +3313,25 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } + "dev": true }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } + "dev": true }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "dev": true }, "es6-weak-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } + "dev": true }, "escape-html": { "version": "1.0.3", @@ -5328,13 +3350,6 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, "dependencies": { "esprima": { "version": "2.7.3", @@ -5353,10 +3368,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true } } }, @@ -5364,59 +3376,13 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "dev": true }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -5428,39 +3394,37 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true } } }, @@ -5475,19 +3439,12 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5498,42 +3455,28 @@ } }, "eslint-module-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", - "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^2.0.0" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "dev": true }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5545,19 +3488,13 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } + "dev": true }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -5569,71 +3506,39 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } + "dev": true } } }, "eslint-plugin-import": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", - "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.0", - "has": "^1.0.3", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "read-pkg-up": "^2.0.0", - "resolve": "^1.11.0" - }, + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "dev": true }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } + "dev": true }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5645,19 +3550,13 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } + "dev": true }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -5669,19 +3568,13 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } + "dev": true }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -5693,22 +3586,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } + "dev": true } } }, @@ -5717,12 +3601,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, - "requires": { - "ignore": "^3.3.6", - "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "5.3.0" - }, "dependencies": { "semver": { "version": "5.3.0", @@ -5752,11 +3630,7 @@ "version": "3.7.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "dev": true }, "eslint-visitor-keys": { "version": "1.0.0", @@ -5768,11 +3642,7 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } + "dev": true }, "esprima": { "version": "4.0.1", @@ -5784,19 +3654,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } + "dev": true }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } + "dev": true }, "estraverse": { "version": "4.2.0", @@ -5805,9 +3669,9 @@ "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "etag": { @@ -5820,26 +3684,13 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } + "dev": true }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - }, "dependencies": { "map-stream": { "version": "0.1.0", @@ -5865,35 +3716,45 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } + "dev": true }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, "dependencies": { "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "dev": true + } + } + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true } } }, @@ -5902,42 +3763,24 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "dev": true }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -5947,52 +3790,37 @@ } } }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "dependencies": { + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "dev": true }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, "dependencies": { "cookie": { "version": "0.4.0", @@ -6004,23 +3832,13 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true }, "ms": { "version": "2.0.0", @@ -6045,21 +3863,6 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, "dependencies": { "ms": { "version": "2.1.1", @@ -6088,19 +3891,12 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } + "dev": true } } }, @@ -6108,75 +3904,43 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } + "dev": true }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } + "dev": true }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "dev": true } } }, @@ -6196,13 +3960,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } + "dev": true }, "fast-deep-equal": { "version": "1.1.0", @@ -6226,54 +3984,37 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } + "dev": true }, "fibers": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", "integrity": "sha512-dl3Ukt08rHVQfY8xGD0ODwyjwrRALtaghuqGH2jByYX1wpY+nAnRQjJ6Dbqq0DnVgNVQ9yibObzbF4IlPyiwPw==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3" - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", "dev": true }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } + "dev": true }, "file-entry-cache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" - } + "dev": true }, "filesize": { "version": "3.6.1", @@ -6286,21 +4027,12 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true } } }, @@ -6309,24 +4041,12 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -6340,46 +4060,25 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } + "dev": true }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } + "dev": true }, "findup-sync": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } + "dev": true }, "fined": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } + "dev": true }, "flagged-respawn": { "version": "1.0.1", @@ -6392,9 +4091,6 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, "dependencies": { "is-buffer": { "version": "2.0.3", @@ -6409,21 +4105,12 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - }, "dependencies": { "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } + "dev": true } } }, @@ -6437,29 +4124,19 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } + "dev": true }, "follow-redirects": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, - "requires": { - "debug": "^3.2.6" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -6473,10 +4150,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } + "dev": true }, "foreachasync": { "version": "3.0.0", @@ -6500,21 +4174,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "~1.1" - } + "dev": true }, "forwarded": { "version": "0.1.2", @@ -6526,10 +4186,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } + "dev": true }, "fresh": { "version": "0.5.2", @@ -6547,20 +4204,13 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } + "dev": true }, "fs-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "^1.0.0" - } + "dev": true }, "fs-constants": { "version": "1.0.0", @@ -6573,12 +4223,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, - "requires": { - "jsonfile": "~1.0.1", - "mkdirp": "0.3.x", - "ncp": "~0.4.2", - "rimraf": "~2.2.0" - }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -6592,34 +4236,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } + "dev": true }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", "dev": true, - "requires": { - "fs-extra": "~0.6.1", - "mkdirp": "~0.3.5", - "walk": "^2.3.9" - }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -6641,10 +4264,6 @@ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, "dependencies": { "abbrev": { "version": "1.1.1", @@ -6655,8 +4274,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6668,27 +4286,17 @@ "version": "1.1.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } + "optional": true }, "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "dev": true }, "chownr": { "version": "1.1.1", @@ -6699,20 +4307,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6724,10 +4329,7 @@ "version": "4.1.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } + "optional": true }, "deep-extend": { "version": "0.6.0", @@ -6751,10 +4353,7 @@ "version": "1.2.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } + "optional": true }, "fs.realpath": { "version": "1.0.0", @@ -6766,31 +4365,13 @@ "version": "2.7.4", "bundled": true, "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } + "optional": true }, "glob": { "version": "7.1.3", "bundled": true, "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "optional": true }, "has-unicode": { "version": "2.0.1", @@ -6802,35 +4383,24 @@ "version": "0.4.24", "bundled": true, "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "optional": true }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } + "optional": true }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } + "optional": true }, "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6841,11 +4411,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "isarray": { "version": "1.0.0", @@ -6856,45 +4422,28 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } + "dev": true }, "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } + "dev": true }, "minizlib": { "version": "1.2.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } + "optional": true }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } + "dev": true }, "ms": { "version": "2.1.1", @@ -6906,40 +4455,19 @@ "version": "2.3.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } + "optional": true }, "node-pre-gyp": { "version": "0.12.0", "bundled": true, "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } + "optional": true }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } + "optional": true }, "npm-bundled": { "version": "1.0.6", @@ -6951,29 +4479,18 @@ "version": "1.4.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } + "optional": true }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } + "optional": true }, "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6984,11 +4501,7 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } + "dev": true }, "os-homedir": { "version": "1.0.2", @@ -7006,11 +4519,7 @@ "version": "0.1.5", "bundled": true, "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } + "optional": true }, "path-is-absolute": { "version": "1.0.1", @@ -7029,12 +4538,6 @@ "bundled": true, "dev": true, "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, "dependencies": { "minimist": { "version": "1.2.0", @@ -7048,31 +4551,18 @@ "version": "2.3.6", "bundled": true, "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "optional": true }, "rimraf": { "version": "2.6.3", "bundled": true, "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } + "optional": true }, "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7104,34 +4594,21 @@ "dev": true, "optional": true }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string_decoder": { "version": "1.1.1", "bundled": true, "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -7143,16 +4620,7 @@ "version": "4.4.8", "bundled": true, "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } + "optional": true }, "util-deprecate": { "version": "1.0.2", @@ -7164,29 +4632,24 @@ "version": "1.1.3", "bundled": true, "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } + "optional": true }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, "fun-hooks": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.3.tgz", - "integrity": "sha512-MC/zsGf+duq8lI6xym+H8HuL6DE1fLyE90FRzU/j2lTDmjDJ//+KC7M8vLzG9y/mhkLOH5u9wK4QEf3lBqIo4w==" + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/fun-hooks/-/fun-hooks-0.9.5.tgz", + "integrity": "sha512-xaj0r9Ex0dvehX8MbQSK/5EYVAddyoaK2sGNuQWX8xNaCiHtr/4zD9J10Y2irkFIsuaxbYOsQBKXvTHzjO2IFQ==" }, "function-bind": { "version": "1.1.1", @@ -7204,10 +4667,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -7249,39 +4709,25 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } + "dev": true }, "git-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.1.0.tgz", "integrity": "sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "parse-url": "^3.0.2" - } + "dev": true }, "git-url-parse": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true, - "requires": { - "git-up": "^2.0.0", - "parse-domain": "^2.0.0" - } + "dev": true }, "github-slugger": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", "integrity": "sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q==", "dev": true, - "requires": { - "emoji-regex": ">=6.0.0 <=6.1.1" - }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -7295,14 +4741,32 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true + } } }, "glob-parent": { @@ -7310,19 +4774,12 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "dev": true } } }, @@ -7330,57 +4787,25 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } + "dev": true }, "glob-watcher": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "object.defaults": "^1.1.0" - } + "dev": true }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } + "dev": true }, "global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } + "dev": true }, "globals": { "version": "11.12.0", @@ -7398,46 +4823,19 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } + "dev": true }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "dev": true }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", "dev": true, - "requires": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" - }, "dependencies": { "pify": { "version": "3.0.0", @@ -7448,9 +4846,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz", + "integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==", "dev": true }, "grapheme-splitter": { @@ -7470,21 +4868,12 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, "dependencies": { "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } + "dev": true }, "camelcase": { "version": "3.0.0", @@ -7496,22 +4885,13 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } + "dev": true }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } + "dev": true }, "get-caller-file": { "version": "1.0.3", @@ -7523,27 +4903,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.1.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.0.1", - "yargs": "^7.1.0" - } + "dev": true }, "invert-kv": { "version": "1.0.0", @@ -7555,70 +4915,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "dev": true }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } + "dev": true }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } + "dev": true }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } + "dev": true }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } + "dev": true }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -7630,22 +4963,13 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } + "dev": true }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "require-main-filename": { "version": "1.0.1", @@ -7657,21 +4981,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "dev": true }, "which-module": { "version": "1.0.0", @@ -7689,31 +5005,13 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - } + "dev": true }, "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } + "dev": true } } }, @@ -7722,11 +5020,6 @@ "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", "dev": true, - "requires": { - "gulp-util": "^2.2.14", - "rimraf": "^2.2.8", - "through2": "^0.4.2" - }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -7744,14 +5037,7 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" - } + "dev": true }, "clone-stats": { "version": "0.0.1", @@ -7764,26 +5050,12 @@ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", "dev": true, - "requires": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" - }, "dependencies": { "through2": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" - } + "dev": true } } }, @@ -7791,10 +5063,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.0" - } + "dev": true }, "isarray": { "version": "0.0.1", @@ -7818,13 +5087,7 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -7836,10 +5099,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.1" - } + "dev": true }, "supports-color": { "version": "0.2.0", @@ -7852,19 +5112,12 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~2.1.1" - }, "dependencies": { "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "~0.4.0" - } + "dev": true } } }, @@ -7872,10 +5125,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "~0.0.1" - } + "dev": true }, "xtend": { "version": "3.0.0", @@ -7889,34 +5139,18 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - } + "dev": true }, "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", - "integrity": "sha1-fpJfXkw06/7fnzGFdpZuj+iEDVo=", - "dev": true, - "requires": { - "ansi-colors": "^2.0.5", - "connect": "^3.6.6", - "connect-livereload": "^0.6.0", - "fancy-log": "^1.3.2", - "map-stream": "^0.0.7", - "send": "^0.16.2", - "serve-index": "^1.9.1", - "serve-static": "^1.13.2", - "tiny-lr": "^1.1.1" - }, + "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", + "dev": true, "dependencies": { "ansi-colors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz", - "integrity": "sha1-XaN4Jf7z51872kf3YNZL/RDhXhA=", + "integrity": "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==", "dev": true } } @@ -7925,24 +5159,11 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true, - "requires": { - "eslint": "^4.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.0" - } + "dev": true }, "gulp-footer": { "version": "github:prebid/gulp-footer#ff2b46e6376c7f04900357ff9f7b30f219fe5f8a", - "from": "github:prebid/gulp-footer#master", "dev": true, - "requires": { - "event-stream": "3.3.4", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.6.2" - }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -7954,48 +5175,25 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } + "dev": true }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } + "dev": true }, "lodash.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } + "dev": true } } }, @@ -8004,11 +5202,6 @@ "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, - "requires": { - "concat-with-sourcemaps": "*", - "lodash.template": "^4.4.0", - "through2": "^2.0.0" - }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -8017,23 +5210,16 @@ "dev": true }, "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true }, "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true } } }, @@ -8041,21 +5227,13 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "^1.0.3", - "ternary-stream": "^2.0.1", - "through2": "^2.0.1" - } + "dev": true }, "gulp-js-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", "dev": true, - "requires": { - "through2": "^0.6.3" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -8067,13 +5245,7 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -8085,64 +5257,33 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } + "dev": true } } }, "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true, - "requires": { - "minimatch": "^3.0.3" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", + "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", + "dev": true }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", - "dev": true, - "requires": { - "istextorbinary": "2.2.1", - "readable-stream": "^2.0.1", - "replacestream": "^4.0.0" - } + "dev": true }, "gulp-shell": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true, - "requires": { - "async": "^1.5.0", - "gulp-util": "^3.0.7", - "lodash": "^4.0.0", - "through2": "^2.0.0" - } + "dev": true }, "gulp-sourcemaps": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.X", - "@gulp-sourcemaps/map-sources": "1.X", - "acorn": "5.X", - "convert-source-map": "1.X", - "css": "2.X", - "debug-fabulous": "1.X", - "detect-newline": "2.X", - "graceful-fs": "4.X", - "source-map": "~0.6.0", - "strip-bom-string": "1.X", - "through2": "2.X" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -8156,45 +5297,13 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "extend-shallow": "^3.0.2", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "isobject": "^3.0.1", - "make-error-cause": "^1.1.1", - "safe-buffer": "^5.1.2", - "through2": "^2.0.0", - "uglify-js": "^3.0.5", - "vinyl-sourcemaps-apply": "^0.2.0" - } + "dev": true }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -8206,14 +5315,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } + "dev": true }, "clone": { "version": "1.0.4", @@ -8243,48 +5345,25 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } + "dev": true }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } + "dev": true }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } + "dev": true }, "lodash.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } + "dev": true }, "object-assign": { "version": "3.0.0", @@ -8308,12 +5387,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } + "dev": true } } }, @@ -8321,32 +5395,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } + "dev": true }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "pify": "^4.0.1" - } + "dev": true }, "handlebars": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -8367,22 +5428,12 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true }, "fast-deep-equal": { "version": "2.0.1", @@ -8402,28 +5453,19 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } + "dev": true }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, - "requires": { - "isarray": "2.0.1" - }, "dependencies": { "isarray": { "version": "2.0.1", @@ -8449,10 +5491,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } + "dev": true }, "has-symbol-support-x": { "version": "1.4.2", @@ -8470,40 +5509,25 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "requires": { - "has-symbol-support-x": "^1.4.1" - } + "dev": true }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } + "dev": true }, "has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -8511,21 +5535,13 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } + "dev": true }, "hast-util-is-element": { "version": "1.0.3", @@ -8537,29 +5553,13 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.1.tgz", "integrity": "sha512-AIeKHuHx0Wk45nSkGVa2/ujQYTksnDl8gmmKo/mwQi7ag7IBZ8cM3nJ2G86SajbjGP/HRpud6kMkPtcM2i0Tlw==", - "dev": true, - "requires": { - "xtend": "^4.0.1" - } + "dev": true }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", "dev": true, - "requires": { - "ccount": "^1.0.0", - "comma-separated-tokens": "^1.0.1", - "hast-util-is-element": "^1.0.0", - "hast-util-whitespace": "^1.0.0", - "html-void-elements": "^1.0.0", - "kebab-case": "^1.0.0", - "property-information": "^3.1.0", - "space-separated-tokens": "^1.0.0", - "stringify-entities": "^1.0.1", - "unist-util-is": "^2.0.0", - "xtend": "^4.0.1" - }, "dependencies": { "unist-util-is": { "version": "2.1.3", @@ -8582,40 +5582,28 @@ "dev": true }, "highlight.js": { - "version": "9.15.8", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", - "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA==", + "version": "9.15.9", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.9.tgz", + "integrity": "sha512-M0zZvfLr5p0keDMCAhNBp03XJbKBxUx5AfyfufMdFMEP4N/Xj6dh0IqC75ys7BAzceR34NgcvXjupRVaHBPPVQ==", "dev": true }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } + "dev": true }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } + "dev": true }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } + "dev": true }, "hoopy": { "version": "0.1.4", @@ -8624,9 +5612,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.2.tgz", + "integrity": "sha512-CyjlXII6LMsPMyUzxpTt8fzh5QwzGqPmQXgY/Jyf4Zfp27t/FvfhwoE/8laaMUcMy816CkWF20I7NeQhwwY88w==", "dev": true }, "html-void-elements": { @@ -8643,14 +5631,16 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "http-parser-js": { @@ -8663,23 +5653,13 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } + "dev": true }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } + "dev": true }, "https-browserify": { "version": "1.0.0", @@ -8688,23 +5668,16 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", + "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -8718,10 +5691,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "dev": true }, "ieee754": { "version": "1.1.13", @@ -8729,12 +5699,6 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -8751,10 +5715,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } + "dev": true }, "indexof": { "version": "0.0.1", @@ -8766,16 +5727,12 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } + "dev": true }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { @@ -8789,22 +5746,6 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -8816,10 +5757,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "dev": true } } }, @@ -8833,20 +5771,13 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, - "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" - } + "dev": true }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } + "dev": true }, "invert-kv": { "version": "2.0.0", @@ -8864,29 +5795,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } + "dev": true }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -8906,16 +5827,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, "is-arrayish": { @@ -8928,10 +5839,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } + "dev": true }, "is-buffer": { "version": "1.1.6", @@ -8950,18 +5858,12 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -8982,11 +5884,6 @@ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -9002,6 +5899,18 @@ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", "dev": true }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -9018,10 +5927,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -9029,20 +5935,11 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "dev": true - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } + "dev": true }, "is-hexadecimal": { "version": "1.0.3", @@ -9061,18 +5958,12 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -9092,10 +5983,19 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true }, "is-promise": { "version": "2.1.0", @@ -9107,19 +6007,13 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } + "dev": true }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } + "dev": true }, "is-resolvable": { "version": "1.1.0", @@ -9143,10 +6037,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", - "dev": true, - "requires": { - "protocols": "^1.1.0" - } + "dev": true }, "is-stream": { "version": "1.1.0", @@ -9158,10 +6049,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } + "dev": true }, "is-typedarray": { "version": "1.0.0", @@ -9173,10 +6061,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } + "dev": true }, "is-utf8": { "version": "0.2.1", @@ -9224,10 +6109,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } + "dev": true }, "isexe": { "version": "2.0.0", @@ -9252,22 +6134,6 @@ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, "dependencies": { "esprima": { "version": "2.7.3", @@ -9279,14 +6145,7 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "dev": true }, "has-flag": { "version": "1.0.0", @@ -9304,10 +6163,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true } } }, @@ -9316,28 +6172,12 @@ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, - "requires": { - "async": "^2.1.4", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.1", - "istanbul-lib-hook": "^1.2.2", - "istanbul-lib-instrument": "^1.10.2", - "istanbul-lib-report": "^1.1.5", - "istanbul-lib-source-maps": "^1.2.6", - "istanbul-reports": "^1.5.1", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" - }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true } } }, @@ -9345,13 +6185,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true, - "requires": { - "convert-source-map": "^1.5.0", - "istanbul-lib-instrument": "^1.7.3", - "loader-utils": "^1.1.0", - "schema-utils": "^0.3.0" - } + "dev": true }, "istanbul-lib-coverage": { "version": "1.2.1", @@ -9363,37 +6197,19 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true, - "requires": { - "append-transform": "^0.4.0" - } + "dev": true }, "istanbul-lib-instrument": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } + "dev": true }, "istanbul-lib-report": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -9405,10 +6221,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } + "dev": true } } }, @@ -9417,31 +6230,18 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } + "dev": true } } }, @@ -9449,31 +6249,19 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true, - "requires": { - "handlebars": "^4.0.3" - } + "dev": true }, "istextorbinary": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true, - "requires": { - "binaryextensions": "2", - "editions": "^1.3.3", - "textextensions": "2" - } + "dev": true }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - } + "dev": true }, "js-levenshtein": { "version": "1.1.6", @@ -9491,11 +6279,7 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } + "dev": true }, "jsbn": { "version": "0.1.1", @@ -9560,10 +6344,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } + "dev": true }, "jsonfile": { "version": "1.0.1", @@ -9583,17 +6364,17 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } + "dev": true }, "just-clone": { "version": "1.0.2", @@ -9613,165 +6394,28 @@ "dev": true }, "karma": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz", - "integrity": "sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==", - "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "braces": "^3.0.2", - "chokidar": "^3.0.0", - "colors": "^1.1.0", - "connect": "^3.6.0", - "core-js": "^3.1.3", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "flatted": "^2.0.0", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.11", - "log4js": "^4.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", - "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" - }, + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", + "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "dev": true, "dependencies": { - "anymatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz", - "integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", - "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", - "dev": true, - "requires": { - "anymatch": "^3.0.1", - "braces": "^3.0.2", - "fsevents": "^2.0.6", - "glob-parent": "^5.0.0", - "is-binary-path": "^2.1.0", - "is-glob": "^4.0.1", - "normalize-path": "^3.0.0", - "readdirp": "^3.1.1" - } - }, - "core-js": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", - "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", - "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, - "readdirp": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.1.tgz", - "integrity": "sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.4" - } - }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } + "dev": true }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } } } }, @@ -9779,21 +6423,13 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true, - "requires": { - "babel-core": "^6.0.0" - } + "dev": true }, "karma-browserstack-launcher": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.1.tgz", "integrity": "sha512-zt9Ukow5A9WZHZXCFVO/h5kRsAdaZYeMNJK9Uan8v42amQXt3B/DZVxl24NCcAIxufKjW13UWd9iJ9knG9OCYw==", - "dev": true, - "requires": { - "browserstack": "~1.5.1", - "browserstack-local": "^1.3.7", - "q": "~1.5.0" - } + "dev": true }, "karma-chai": { "version": "0.1.0", @@ -9805,30 +6441,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true, - "requires": { - "fs-access": "^1.0.0", - "which": "^1.2.1" - } + "dev": true }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true, - "requires": { - "istanbul-api": "^1.3.1", - "minimatch": "^3.0.4" - } + "dev": true }, "karma-es5-shim": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", - "dev": true, - "requires": { - "es5-shim": "^4.0.5" - } + "dev": true }, "karma-firefox-launcher": { "version": "1.1.0", @@ -9840,30 +6465,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true, - "requires": { - "lodash": "^4.6.1" - } + "dev": true }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "requires": { - "minimist": "1.2.0" - } + "dev": true }, "karma-mocha-reporter": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "strip-ansi": "^4.0.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -9875,10 +6489,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "dev": true } } }, @@ -9910,42 +6521,25 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } + "dev": true }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true, - "requires": { - "colors": "^1.1.2" - } + "dev": true }, "karma-webpack": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", "dev": true, - "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^2.0.6" - }, "dependencies": { "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true } } }, @@ -9959,10 +6553,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } + "dev": true }, "kind-of": { "version": "6.0.2", @@ -9974,11 +6565,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } + "dev": true }, "lazy-cache": { "version": "1.0.4", @@ -9990,19 +6577,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } + "dev": true }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } + "dev": true }, "lcov-parse": { "version": "0.0.10", @@ -10014,36 +6595,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } + "dev": true }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } + "dev": true }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } + "dev": true }, "livereload-js": { "version": "2.4.0", @@ -10056,12 +6620,6 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, "dependencies": { "pify": { "version": "3.0.0", @@ -10082,20 +6640,12 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, "dependencies": { "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } + "dev": true } } }, @@ -10103,11 +6653,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } + "dev": true }, "lodash": { "version": "4.17.15", @@ -10137,10 +6683,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "requires": { - "lodash._htmlescapes": "~2.4.1" - } + "dev": true }, "lodash._escapestringchar": { "version": "2.4.1", @@ -10200,11 +6743,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash._root": { "version": "3.0.1", @@ -10216,10 +6755,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } + "dev": true }, "lodash.clone": { "version": "4.5.0", @@ -10231,22 +6767,13 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash.escape": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" - } + "dev": true }, "lodash.get": { "version": "4.4.2", @@ -10270,21 +6797,13 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } + "dev": true }, "lodash.keys": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } + "dev": true }, "lodash.restparam": { "version": "3.6.1", @@ -10302,35 +6821,19 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "requires": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" - } + "dev": true }, "lodash.templatesettings": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" - } + "dev": true }, "lodash.values": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", - "dev": true, - "requires": { - "lodash.keys": "~2.4.1" - } + "dev": true }, "log-driver": { "version": "1.2.7", @@ -10342,38 +6845,38 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } + "dev": true }, "log4js": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", - "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, - "requires": { - "date-format": "^2.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.0", - "rfdc": "^1.1.4", - "streamroller": "^1.0.6" + "dependencies": { + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true + } } }, "loglevelnext": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "dev": true, - "requires": { - "es6-symbol": "^3.1.1", - "object.assign": "^4.1.0" - } + "dev": true }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", "dev": true }, "longest": { @@ -10392,20 +6895,13 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } + "dev": true }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } + "dev": true }, "lowercase-keys": { "version": "1.0.1", @@ -10414,33 +6910,22 @@ "dev": true }, "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } + "dev": true }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } + "dev": true }, "make-error": { "version": "1.3.5", @@ -10452,34 +6937,19 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "^1.2.0" - } + "dev": true }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", "dev": true }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } + "dev": true }, "map-cache": { "version": "0.2.2", @@ -10503,10 +6973,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } + "dev": true }, "markdown-escapes": { "version": "1.0.3", @@ -10525,92 +6992,56 @@ "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, "dependencies": { "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } + "dev": true }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "dev": true } } }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "dev": true }, "mdast-util-compact": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } + "dev": true }, "mdast-util-definitions": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz", "integrity": "sha512-HfUArPog1j4Z78Xlzy9Q4aHLnrF/7fb57cooTHypyGoe2XFNbcx/kWZDoOz+ra8CkUzvg3+VHV434yqEd1DRmA==", - "dev": true, - "requires": { - "unist-util-visit": "^1.0.0" - } + "dev": true }, "mdast-util-inject": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.0" - } + "dev": true }, "mdast-util-to-hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz", "integrity": "sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.0", - "detab": "^2.0.0", - "mdast-util-definitions": "^1.2.0", - "mdurl": "^1.0.1", - "trim": "0.0.1", - "trim-lines": "^1.0.0", - "unist-builder": "^1.0.1", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.0", - "xtend": "^4.0.1" - } + "dev": true }, "mdast-util-to-string": { "version": "1.0.6", @@ -10623,12 +7054,6 @@ "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.1.0.tgz", "integrity": "sha512-Za0hqL1PqWrvxGtA/3NH9D5nhGAUS9grMM4obEAz5+zsk1RIw/vWUchkaoDLNdrwk05A0CSC5eEXng36/1qE5w==", "dev": true, - "requires": { - "github-slugger": "^1.2.1", - "mdast-util-to-string": "^1.0.5", - "unist-util-is": "^2.1.2", - "unist-util-visit": "^1.1.0" - }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -10640,10 +7065,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", "integrity": "sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==", - "dev": true, - "requires": { - "emoji-regex": ">=6.0.0 <=6.1.1" - } + "dev": true }, "unist-util-is": { "version": "2.1.3", @@ -10670,11 +7092,6 @@ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, "dependencies": { "p-is-promise": { "version": "2.1.0", @@ -10688,27 +7105,13 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } + "dev": true }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } + "dev": true }, "memorystream": { "version": "0.3.1", @@ -10721,70 +7124,36 @@ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, "dependencies": { "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } + "dev": true }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } + "dev": true }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } + "dev": true }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } + "dev": true }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -10796,31 +7165,19 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } + "dev": true }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } + "dev": true }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "dev": true } } }, @@ -10834,10 +7191,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "dev": true }, "methods": { "version": "1.1.2", @@ -10849,32 +7203,13 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } + "dev": true }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } + "dev": true }, "mime": { "version": "1.6.0", @@ -10892,10 +7227,7 @@ "version": "2.1.24", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } + "dev": true }, "mimic-fn": { "version": "2.1.0", @@ -10925,53 +7257,25 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } + "dev": true }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } + "dev": true } } }, @@ -10980,13 +7284,10 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "requires": { - "minimist": "0.0.8" - }, "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } @@ -10997,19 +7298,6 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, "dependencies": { "commander": { "version": "2.15.1", @@ -11021,10 +7309,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "diff": { "version": "3.5.0", @@ -11036,15 +7321,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "dev": true }, "he": { "version": "1.1.1", @@ -11062,10 +7339,7 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "dev": true } } }, @@ -11074,47 +7348,18 @@ "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^1.7.0", - "concat-stream": "~1.5.0", - "defined": "^1.0.0", - "detective": "^4.0.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.3", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" - }, "dependencies": { "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } + "dev": true } } }, @@ -11132,31 +7377,6 @@ } } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -11168,18 +7388,12 @@ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, - "requires": { - "duplexer2": "0.0.2" - }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - } + "dev": true }, "isarray": { "version": "0.0.1", @@ -11191,13 +7405,7 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -11230,20 +7438,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } + "dev": true }, "natural-compare": { "version": "1.4.0", @@ -11282,32 +7477,21 @@ "dev": true }, "nise": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", - "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz", + "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==", "dev": true, - "requires": { - "@sinonjs/formatio": "^3.1.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^4.1.0", - "path-to-regexp": "^1.7.0" - }, "dependencies": { "@sinonjs/formatio": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } + "dev": true }, "lolex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", - "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", "dev": true } } @@ -11316,100 +7500,45 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } + "dev": true }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, "dependencies": { "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } + "dev": true }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } } } }, "node-releases": { - "version": "1.1.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.23.tgz", - "integrity": "sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } + "version": "1.1.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", + "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", + "dev": true }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } + "dev": true }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } + "dev": true }, "normalize-path": { "version": "3.0.0", @@ -11421,22 +7550,13 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } + "dev": true }, "now-and-later": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } + "dev": true }, "npm-install-package": { "version": "2.1.0", @@ -11448,27 +7568,13 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - } + "dev": true }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } + "dev": true }, "null-check": { "version": "1.0.0", @@ -11505,29 +7611,18 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "dev": true }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -11541,112 +7636,81 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } + "dev": true }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } + "dev": true }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } + "dev": true }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } + "dev": true }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true + } } }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "dev": true }, "object.reduce": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "dev": true + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } + "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } + "dev": true }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, "dependencies": { "mimic-fn": { "version": "1.2.0", @@ -11666,24 +7730,17 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } + "dev": true }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -11699,24 +7756,13 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } + "dev": true }, "ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "dev": true }, "os-browserify": { "version": "0.3.0", @@ -11734,12 +7780,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } + "dev": true }, "os-tmpdir": { "version": "1.0.2", @@ -11775,28 +7816,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } + "dev": true }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } + "dev": true }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } + "dev": true }, "p-try": { "version": "2.2.0", @@ -11810,52 +7842,23 @@ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "~0.11.15" - } + "dev": true }, "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } + "dev": true }, "parse-domain": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", "dev": true, - "requires": { - "chai": "^4.2.0", - "got": "^8.3.2", - "mkdirp": "^0.5.1", - "mocha": "^6.1.4", - "npm-run-all": "^4.1.5" - }, "dependencies": { "ansi-regex": { "version": "4.1.0", @@ -11867,10 +7870,7 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true }, "diff": { "version": "3.5.0", @@ -11882,46 +7882,13 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "dev": true }, "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - } + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "dev": true }, "ms": { "version": "2.1.1", @@ -11933,49 +7900,25 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } + "dev": true }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } + "dev": true }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "dev": true }, "yargs": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } + "dev": true } } }, @@ -11983,45 +7926,45 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } + "dev": true }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } + "dev": true }, "parse-git-config": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, - "requires": { - "ini": "^1.3.3" + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true + } } }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } + "dev": true }, "parse-node-version": { "version": "1.0.1", @@ -12039,41 +7982,25 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-3.0.4.tgz", "integrity": "sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0" - } + "dev": true }, "parse-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-3.0.2.tgz", "integrity": "sha1-YCeHpwY6eV1yuGcxl1BecvYGEL4=", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "normalize-url": "^1.9.1", - "parse-path": "^3.0.1", - "protocols": "^1.4.0" - } + "dev": true }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "dev": true }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "dev": true }, "parseurl": { "version": "1.3.3", @@ -12139,10 +8066,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } + "dev": true }, "path-root-regex": { "version": "0.1.2", @@ -12155,9 +8079,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, - "requires": { - "isarray": "0.0.1" - }, "dependencies": { "isarray": { "version": "0.0.1", @@ -12172,9 +8093,6 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, - "requires": { - "pify": "^3.0.0" - }, "dependencies": { "pify": { "version": "3.0.0", @@ -12194,23 +8112,19 @@ "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } + "dev": true }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } + "dev": true + }, + "pbkdf2-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", + "dev": true }, "performance-now": { "version": "2.1.0", @@ -12218,12 +8132,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "picomatch": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", - "dev": true - }, "pidtree": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", @@ -12246,40 +8154,25 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } + "dev": true }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } + "dev": true }, "plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, "dependencies": { "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } + "dev": true } } }, @@ -12307,6 +8200,12 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12326,9 +8225,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "progress": { @@ -12337,12 +8236,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12359,11 +8252,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } + "dev": true }, "prr": { "version": "1.0.1", @@ -12375,10 +8264,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz", "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", - "dev": true, - "requires": { - "event-stream": "=3.3.4" - } + "dev": true }, "pseudomap": { "version": "1.0.2", @@ -12387,55 +8273,34 @@ "dev": true }, "psl": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", - "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", + "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", "dev": true }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "dev": true }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "dev": true }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, "dependencies": { "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "dev": true } } }, @@ -12467,11 +8332,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } + "dev": true }, "querystring": { "version": "0.2.0", @@ -12491,24 +8352,31 @@ "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", "dev": true }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } + "dev": true }, "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } + "dev": true }, "range-parser": { "version": "1.2.1", @@ -12521,10 +8389,6 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, - "requires": { - "bytes": "1", - "string_decoder": "0.10" - }, "dependencies": { "string_decoder": { "version": "0.10.31", @@ -12538,59 +8402,37 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } + "dev": true }, "read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, "dependencies": { "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "dev": true }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } + "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } + "dev": true }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -12604,46 +8446,25 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "dev": true }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } + "dev": true }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } + "dev": true }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } + "dev": true }, "regenerate": { "version": "1.4.0", @@ -12655,10 +8476,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } + "dev": true }, "regenerator-runtime": { "version": "0.11.1", @@ -12666,28 +8484,27 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz", - "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==", - "dev": true, - "requires": { - "private": "^0.1.6" - } + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } + "dev": true }, "regexp-tree": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.10.tgz", - "integrity": "sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", + "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==", "dev": true }, "regexpp": { @@ -12700,15 +8517,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } + "dev": true }, "regjsgen": { "version": "0.5.0", @@ -12721,9 +8530,6 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -12737,129 +8543,61 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true, - "requires": { - "remark-parse": "^5.0.0", - "remark-stringify": "^5.0.0", - "unified": "^6.0.0" - } + "dev": true }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true, - "requires": { - "hast-util-sanitize": "^1.0.0", - "hast-util-to-html": "^3.0.0", - "mdast-util-to-hast": "^3.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } + "dev": true }, "remark-reference-links": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.4.tgz", "integrity": "sha512-+2X8hwSQqxG4tvjYZNrTcEC+bXp8shQvwRGG6J/rnFTvBoU4G0BBviZoqKGZizLh/DG+0gSYhiDDWCqyxXW1iQ==", - "dev": true, - "requires": { - "unist-util-visit": "^1.0.0" - } + "dev": true }, "remark-slug": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.2.tgz", "integrity": "sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==", - "dev": true, - "requires": { - "github-slugger": "^1.0.0", - "mdast-util-to-string": "^1.0.0", - "unist-util-visit": "^1.0.0" - } + "dev": true }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } + "dev": true }, "remark-toc": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.1.1.tgz", "integrity": "sha512-vCPW4YOsm2CfyuScdktM9KDnJXVHJsd/ZeRtst+dnBU3B3KKvt8bc+bs5syJjyptAHfqo7H+5Uhz+2blWBfwow==", - "dev": true, - "requires": { - "mdast-util-toc": "^3.0.0", - "remark-slug": "^5.0.0" - } + "dev": true }, "remote-origin-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true, - "requires": { - "parse-git-config": "^0.2.0" - } + "dev": true }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } + "dev": true }, "remove-bom-stream": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } + "dev": true }, "remove-trailing-separator": { "version": "1.1.0", @@ -12883,10 +8621,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } + "dev": true }, "replace-ext": { "version": "1.0.0", @@ -12898,72 +8633,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } + "dev": true }, "replacestream": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.3", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.2" - } + "dev": true }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } + "dev": true }, "request-promise": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", - "dev": true, - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } + "dev": true }, "request-promise-core": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "dev": true }, "require-directory": { "version": "2.1.1", @@ -12982,10 +8676,6 @@ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, "dependencies": { "resolve-from": { "version": "1.0.1", @@ -13002,23 +8692,16 @@ "dev": true }, "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true }, "resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } + "dev": true }, "resolve-from": { "version": "5.0.0", @@ -13030,10 +8713,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } + "dev": true }, "resolve-url": { "version": "0.2.1", @@ -13045,20 +8725,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } + "dev": true }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } + "dev": true }, "ret": { "version": "0.1.15", @@ -13082,10 +8755,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } + "dev": true }, "rimraf": { "version": "2.2.8", @@ -13097,29 +8767,13 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } + "dev": true }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } + "dev": true }, "rx-lite": { "version": "4.0.8", @@ -13131,10 +8785,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } + "dev": true }, "safe-buffer": { "version": "5.1.2", @@ -13152,10 +8803,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -13164,19 +8812,16 @@ "dev": true }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, "schema-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "^5.0.0" - } + "dev": true }, "semver": { "version": "5.7.0", @@ -13188,40 +8833,19 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } + "dev": true }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "mime": { "version": "1.4.1", @@ -13243,35 +8867,17 @@ } } }, - "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", - "dev": true - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -13286,21 +8892,12 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "requires": { - "ms": "2.0.0" - }, "dependencies": { "ms": { "version": "2.0.0", @@ -13311,17 +8908,10 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true }, "ms": { "version": "2.1.1", @@ -13333,22 +8923,7 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - } + "dev": true }, "setprototypeof": { "version": "1.1.1", @@ -13369,21 +8944,12 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true } } }, @@ -13403,20 +8969,13 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } + "dev": true }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } + "dev": true }, "shebang-regex": { "version": "1.0.0", @@ -13428,24 +8987,13 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "dev": true }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } + "dev": true }, "signal-exit": { "version": "3.0.2", @@ -13458,27 +9006,12 @@ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "dev": true, - "requires": { - "@sinonjs/formatio": "^2.0.0", - "diff": "^3.1.0", - "lodash.get": "^4.4.2", - "lolex": "^2.2.0", - "nise": "^1.2.0", - "supports-color": "^5.1.0", - "type-detect": "^4.0.5" - }, "dependencies": { "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true - }, - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true } } }, @@ -13492,53 +9025,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } + "dev": true }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "dev": true }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "dev": true }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "dev": true }, "ms": { "version": "2.0.0", @@ -13553,49 +9064,30 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } + "dev": true }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "dev": true } } }, @@ -13604,43 +9096,26 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, - "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -13659,24 +9134,8 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -13687,11 +9146,8 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "ms": { "version": "2.0.0", @@ -13703,14 +9159,9 @@ }, "socket.io-parser": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -13721,11 +9172,8 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true }, "isarray": { "version": "2.0.1", @@ -13745,10 +9193,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } + "dev": true }, "source-list-map": { "version": "2.0.1", @@ -13766,23 +9211,13 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } + "dev": true }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } + "dev": true }, "source-map-url": { "version": "0.4.0", @@ -13806,11 +9241,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } + "dev": true }, "spdx-exceptions": { "version": "2.2.0", @@ -13822,35 +9253,25 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } + "dev": true }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2" - } + "dev": true }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -13862,27 +9283,7 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } + "dev": true }, "stack-trace": { "version": "0.0.10", @@ -13901,19 +9302,12 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "dev": true } } }, @@ -13934,9 +9328,6 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, - "requires": { - "readable-stream": "~2.1.0" - }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -13948,16 +9339,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true, - "requires": { - "buffer-shims": "^1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } + "dev": true }, "string_decoder": { "version": "0.10.31", @@ -13971,40 +9353,19 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } + "dev": true }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } + "dev": true }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } + "dev": true }, "stream-exhaust": { "version": "1.0.2", @@ -14016,14 +9377,7 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } + "dev": true }, "stream-shift": { "version": "1.0.0", @@ -14032,55 +9386,16 @@ "dev": true }, "streamroller": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", - "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, - "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.14" - }, "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } + "dev": true } } }, @@ -14090,6 +9405,12 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true + }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -14101,10 +9422,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -14116,10 +9433,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } + "dev": true } } }, @@ -14127,42 +9441,19 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^1.0.2" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "dev": true }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } + "dev": true }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } + "dev": true }, "strip-bom": { "version": "3.0.0", @@ -14186,10 +9477,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -14201,43 +9489,25 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "^1.1.0" - } + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "dev": true }, "sver-compat": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } + "dev": true }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } + "dev": true }, "tapable": { "version": "0.2.9", @@ -14249,144 +9519,27 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - } + "dev": true }, "temp-fs": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", "dev": true, - "requires": { - "rimraf": "~2.5.2" - }, "dependencies": { "rimraf": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - } - } - }, - "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true, - "requires": { - "duplexify": "^3.5.0", - "fork-stream": "^0.0.4", - "merge-stream": "^1.0.0", - "through2": "^2.0.1" - } - }, - "terser": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz", - "integrity": "sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } } } }, - "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", - "dev": true, - "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", - "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } + "ternary-stream": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", + "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", + "dev": true }, "text-table": { "version": "0.2.0", @@ -14395,9 +9548,9 @@ "dev": true }, "textextensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", - "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.5.0.tgz", + "integrity": "sha512-1IkVr355eHcomgK7fgj1Xsokturx6L5S2JRT5WcRdA6v5shk9sxWuO/w/VbpQexwkXJMQIa/j1dBi3oo7+HhcA==", "dev": true }, "through": { @@ -14410,21 +9563,13 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } + "dev": true }, "through2-filter": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } + "dev": true }, "time-stamp": { "version": "1.1.0", @@ -14442,43 +9587,25 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } + "dev": true }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } + "dev": true }, "tiny-lr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", "dev": true, - "requires": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "dev": true } } }, @@ -14486,20 +9613,13 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } + "dev": true }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } + "dev": true }, "to-array": { "version": "0.1.4", @@ -14530,18 +9650,12 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "dev": true } } }, @@ -14549,32 +9663,19 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } + "dev": true }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } + "dev": true }, "to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } + "dev": true }, "toidentifier": { "version": "1.0.0", @@ -14587,10 +9688,6 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, "dependencies": { "punycode": { "version": "1.4.1", @@ -14642,12 +9739,6 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -14658,10 +9749,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } + "dev": true }, "tweetnacl": { "version": "0.14.5", @@ -14670,19 +9758,16 @@ "dev": true }, "type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", - "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/type/-/type-1.0.3.tgz", + "integrity": "sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg==", "dev": true }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } + "dev": true }, "type-detect": { "version": "4.0.8", @@ -14694,11 +9779,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } + "dev": true }, "typedarray": { "version": "0.0.6", @@ -14711,10 +9792,6 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -14728,19 +9805,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true + "dev": true }, "uglifyjs-webpack-plugin": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, - "requires": { - "source-map": "^0.5.6", - "uglify-js": "^2.8.29", - "webpack-sources": "^1.0.1" - }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -14752,23 +9823,13 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } + "dev": true }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } + "dev": true }, "wordwrap": { "version": "0.0.2", @@ -14780,13 +9841,7 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } + "dev": true } } }, @@ -14806,18 +9861,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } + "dev": true }, "undertaker-registry": { "version": "1.0.1", @@ -14829,11 +9873,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } + "dev": true }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", @@ -14845,11 +9885,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } + "dev": true }, "unicode-match-property-value-ecmascript": { "version": "1.1.0", @@ -14867,64 +9903,25 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } + "dev": true }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } + "dev": true }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } + "dev": true }, "unist-builder": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.4.tgz", "integrity": "sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg==", - "dev": true, - "requires": { - "object-assign": "^4.1.0" - } + "dev": true }, "unist-util-generated": { "version": "1.1.4", @@ -14948,10 +9945,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } + "dev": true }, "unist-util-stringify-position": { "version": "1.1.2", @@ -14963,24 +9957,12 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } + "dev": true }, "unist-util-visit-parents": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "requires": { - "unist-util-is": "^3.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, "unpipe": { @@ -14994,30 +9976,18 @@ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, "dependencies": { "has-value": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, "dependencies": { "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } + "dev": true } } }, @@ -15039,10 +10009,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } + "dev": true }, "urix": { "version": "0.1.0", @@ -15055,10 +10022,6 @@ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, "dependencies": { "punycode": { "version": "1.3.2", @@ -15079,10 +10042,6 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - }, "dependencies": { "querystringify": { "version": "2.1.1", @@ -15097,9 +10056,6 @@ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, - "requires": { - "prepend-http": "^2.0.0" - }, "dependencies": { "prepend-http": { "version": "2.0.0", @@ -15124,24 +10080,35 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } } }, "util": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", - "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, - "requires": { - "inherits": "2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "object.entries": "^1.1.0", - "safe-buffer": "^5.1.2" + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "util-deprecate": { @@ -15166,20 +10133,13 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "dev": true }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } + "dev": true }, "value-or-function": { "version": "3.0.0", @@ -15197,24 +10157,13 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } + "dev": true }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } + "dev": true }, "vfile-location": { "version": "2.0.5", @@ -15226,23 +10175,13 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } + "dev": true }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, - "requires": { - "repeat-string": "^1.5.0", - "string-width": "^1.0.0", - "supports-color": "^4.1.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-statistics": "^1.1.0" - }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -15254,30 +10193,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } + "dev": true } } }, @@ -15297,64 +10225,25 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } + "dev": true }, "vinyl-fs": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } + "dev": true }, "vinyl-sourcemap": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "dev": true } } }, @@ -15362,10 +10251,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } + "dev": true }, "vm-browserify": { "version": "1.1.0", @@ -15383,32 +10269,19 @@ "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", - "dev": true, - "requires": { - "foreachasync": "^3.0.0" - } + "dev": true }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } + "dev": true }, "wdio-browserstack-service": { "version": "0.1.18", "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.18.tgz", "integrity": "sha512-6tISYMKzwr2oxx0yi2Q4GoFC2Mbq81iHhqxayacC4XgFR7QbmQkxwV8JPeq590AXhuhPqqmyuEGkMqc9fo/UoQ==", - "dev": true, - "requires": { - "browserstack-local": "^1.3.7", - "request": "^2.81.0", - "request-promise": "^4.2.1" - } + "dev": true }, "wdio-concise-reporter": { "version": "0.1.2", @@ -15426,64 +10299,25 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/wdio-mocha-framework/-/wdio-mocha-framework-0.6.4.tgz", "integrity": "sha512-GZsXwoW60/fkkfqZJR/ZAdiALaM+hW+BbnTT9x214qPR4Pe5XeyYxhJNEdyf0dNI9625cMdkyZYaWoFHN5zDcA==", - "dev": true, - "requires": { - "babel-runtime": "^6.23.0", - "mocha": "^5.2.0", - "wdio-sync": "0.7.3" - } + "dev": true }, "wdio-spec-reporter": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/wdio-spec-reporter/-/wdio-spec-reporter-0.1.5.tgz", "integrity": "sha512-MqvgTow8hFwhFT47q67JwyJyeynKodGRQCxF7ijKPGfsaG1NLssbXYc0JhiL7SiAyxnQxII0UxzTCd3I6sEdkg==", - "dev": true, - "requires": { - "babel-runtime": "~6.26.0", - "chalk": "^2.3.0", - "humanize-duration": "~3.15.0" - } + "dev": true }, "wdio-sync": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/wdio-sync/-/wdio-sync-0.7.3.tgz", "integrity": "sha512-ukASSHOQmOxaz5HTILR0jykqlHBtAPsBpMtwhpiG0aW9uc7SO7PF+E5LhVvTG4ypAh+UGmY3rTjohOsqDr39jw==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "fibers": "^3.0.0", - "object.assign": "^4.0.3" - } + "dev": true }, "webdriverio": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", "dev": true, - "requires": { - "archiver": "~2.1.0", - "babel-runtime": "^6.26.0", - "css-parse": "^2.0.0", - "css-value": "~0.0.1", - "deepmerge": "~2.0.1", - "ejs": "~2.5.6", - "gaze": "~1.1.2", - "glob": "~7.1.1", - "grapheme-splitter": "^1.0.2", - "inquirer": "~3.3.0", - "json-stringify-safe": "~5.0.1", - "mkdirp": "~0.5.1", - "npm-install-package": "~2.1.0", - "optimist": "~0.6.1", - "q": "~1.5.0", - "request": "^2.83.0", - "rgb2hex": "^0.1.9", - "safe-buffer": "~5.1.1", - "supports-color": "~5.0.0", - "url": "~0.11.0", - "wdio-dot-reporter": "~0.0.8", - "wgxpath": "~1.0.0" - }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -15495,10 +10329,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } + "dev": true } } }, @@ -15507,57 +10338,24 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", "dev": true, - "requires": { - "acorn": "^5.0.0", - "acorn-dynamic-import": "^2.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "async": "^2.1.2", - "enhanced-resolve": "^3.4.0", - "escope": "^3.6.0", - "interpret": "^1.0.0", - "json-loader": "^0.5.4", - "json5": "^0.5.1", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "mkdirp": "~0.5.0", - "node-libs-browser": "^2.0.0", - "source-map": "^0.5.3", - "supports-color": "^4.2.1", - "tapable": "^0.2.7", - "uglifyjs-webpack-plugin": "^0.4.6", - "watchpack": "^1.4.0", - "webpack-sources": "^1.0.1", - "yargs": "^8.0.2" - }, "dependencies": { "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true }, "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true }, "camelcase": { "version": "4.1.0", @@ -15570,22 +10368,12 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, "dependencies": { "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true } } }, @@ -15593,27 +10381,13 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "dev": true }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } + "dev": true }, "fast-deep-equal": { "version": "2.0.1", @@ -15625,10 +10399,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "dev": true }, "get-caller-file": { "version": "1.0.3", @@ -15652,10 +10423,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -15673,41 +10441,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } + "dev": true }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } + "dev": true }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } + "dev": true }, "mimic-fn": { "version": "1.2.0", @@ -15719,30 +10477,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } + "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } + "dev": true }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } + "dev": true }, "p-try": { "version": "1.0.0", @@ -15754,19 +10501,13 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } + "dev": true }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } + "dev": true }, "pify": { "version": "2.3.0", @@ -15778,22 +10519,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } + "dev": true }, "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } + "dev": true }, "require-main-filename": { "version": "1.0.1", @@ -15805,10 +10537,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } + "dev": true }, "y18n": { "version": "3.2.1", @@ -15816,63 +10545,36 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "read-pkg-up": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - } + "dev": true }, "yargs-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } + "dev": true } } }, "webpack-bundle-analyzer": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", - "integrity": "sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==", - "dev": true, - "requires": { - "acorn": "^6.0.7", - "acorn-walk": "^6.1.1", - "bfj": "^6.1.1", - "chalk": "^2.4.1", - "commander": "^2.18.0", - "ejs": "^2.6.1", - "express": "^4.16.3", - "filesize": "^3.6.1", - "gzip-size": "^5.0.0", - "lodash": "^4.17.10", - "mkdirp": "^0.5.1", - "opener": "^1.5.1", - "ws": "^6.0.0" - }, + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", + "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", + "dev": true, "dependencies": { "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "dev": true }, "ejs": { @@ -15885,27 +10587,35 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } + "dev": true + } + } + }, + "webpack-core": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "dev": true, + "dependencies": { + "source-list-map": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true } } }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" - }, "dependencies": { "mime": { "version": "2.4.4", @@ -15919,23 +10629,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "loglevelnext": "^1.0.1", - "uuid": "^3.1.0" - } + "dev": true }, "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, "dependencies": { "source-map": { "version": "0.6.1", @@ -15946,126 +10646,366 @@ } }, "webpack-stream": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-5.2.1.tgz", - "integrity": "sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==", - "dev": true, - "requires": { - "fancy-log": "^1.3.3", - "lodash.clone": "^4.3.2", - "lodash.some": "^4.2.2", - "memory-fs": "^0.4.1", - "plugin-error": "^1.0.1", - "supports-color": "^5.5.0", - "through": "^2.3.8", - "vinyl": "^2.1.0", - "webpack": "^4.26.1" - }, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", + "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", + "dev": true, "dependencies": { "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true + }, + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "dev": true + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "crypto-browserify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", "dev": true }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "dependencies": { + "memory-fs": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", + "dev": true + } } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true }, - "schema-utils": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "has-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "interpret": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true + }, + "memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true + }, + "node-libs-browser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true + }, + "os-browserify": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "ripemd160": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", + "dev": true + }, + "sha.js": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", + "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + }, + "tapable": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "uglify-js": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } } }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true }, - "webpack": { - "version": "4.36.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.36.1.tgz", - "integrity": "sha512-Ej01/N9W8DVyhEpeQnbUdGvOECw0L46FxS12cCOs8gSK7bhUlrbHRnWkjiXckGlHjUrmL89kDpTRIkUk6Y+fKg==", + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.2.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } } + }, + "webpack": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", + "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true } } }, @@ -16073,12 +11013,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } + "dev": true }, "websocket-extensions": { "version": "0.1.3", @@ -16096,10 +11031,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } + "dev": true }, "which-module": { "version": "2.0.0", @@ -16111,10 +11043,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } + "dev": true }, "window-size": { "version": "0.1.0", @@ -16128,44 +11057,23 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, "dependencies": { "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "dev": true }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "dev": true } } }, @@ -16179,21 +11087,13 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } + "dev": true }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } + "dev": true }, "x-is-string": { "version": "0.1.0", @@ -16208,9 +11108,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { @@ -16220,9 +11120,9 @@ "dev": true }, "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true }, "yargs": { @@ -16235,22 +11135,13 @@ "version": "13.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "dev": true }, "yargs-unparser": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, "dependencies": { "get-caller-file": { "version": "1.0.3", @@ -16268,31 +11159,13 @@ "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } + "dev": true }, "yargs-parser": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "dev": true } } }, @@ -16306,13 +11179,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "compress-commons": "^1.2.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0" - } + "dev": true } } } diff --git a/package.json b/package.json index d028e6049a1..dc8af2c21a3 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "is-docker": "^1.1.0", "istanbul": "^0.4.5", "istanbul-instrumenter-loader": "^3.0.0", - "karma": "^4.2.0", + "karma": "^3.1.3", "karma-babel-preprocessor": "^6.0.1", "karma-browserstack-launcher": "^1.3.0", "karma-chai": "^0.1.0", @@ -76,7 +76,7 @@ "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "^0.0.31", "karma-webpack": "^3.0.5", - "lodash": "^4.17.15", + "lodash": "^4.17.4", "mocha": "^5.0.0", "opn": "^5.4.0", "querystringify": "0.0.3", @@ -91,7 +91,7 @@ "webdriverio": "^4.13.2", "webpack": "^3.0.0", "webpack-bundle-analyzer": "^3.3.2", - "webpack-stream": "^5.2.1", + "webpack-stream": "^3.2.0", "yargs": "^1.3.1" }, "dependencies": { From fb59ce4ddcdba97528bdeee17e7b8b0afb40d8cb Mon Sep 17 00:00:00 2001 From: Alex Khmelnitsky Date: Tue, 6 Aug 2019 23:12:59 +0300 Subject: [PATCH 144/436] fix cedato adapter user sync logic (#4060) --- modules/cedatoBidAdapter.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/modules/cedatoBidAdapter.js b/modules/cedatoBidAdapter.js index c367c57fc25..155e6eda107 100644 --- a/modules/cedatoBidAdapter.js +++ b/modules/cedatoBidAdapter.js @@ -107,15 +107,10 @@ export const spec = { getUserSyncs: function(syncOptions, resps, gdprConsent) { const syncs = []; - if (syncOptions.pixelEnabled) { - resps.forEach(() => { - syncs.push(getSync('image', gdprConsent)); - }); - } if (syncOptions.iframeEnabled) { - resps.forEach(() => { - syncs.push(getSync('iframe', gdprConsent)); - }); + syncs.push(getSync('iframe', gdprConsent)); + } else if (syncOptions.pixelEnabled) { + syncs.push(getSync('image', gdprConsent)); } return syncs; } From 8a127545383ab817c9a88174c25f282fcc51b662 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 6 Aug 2019 16:35:50 -0400 Subject: [PATCH 145/436] Prebid 2.27.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc8af2c21a3..222da0c3b00 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.27.0-pre", + "version": "2.27.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 717461dfea530ed5471d7c623b730891c0ba31a3 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 6 Aug 2019 17:39:53 -0400 Subject: [PATCH 146/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 222da0c3b00..b8062204ce1 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.27.0", + "version": "2.28.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8c8cf3212879d614d135dff6b879db31498e533f Mon Sep 17 00:00:00 2001 From: Wayne Yang Date: Wed, 7 Aug 2019 06:41:10 -0700 Subject: [PATCH 147/436] GumGum adapter: push first indexed value in sizes array to bidResponses.height and width (#4006) * changed resizing unit tests to return the first size dimensions in the sizes array * added some changes --- modules/gumgumBidAdapter.js | 4 ++-- test/spec/modules/gumgumBidAdapter_spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 496941e3c1f..75ba5da4de9 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -175,7 +175,7 @@ function buildRequests (validBidRequests, bidderRequest) { tId: transactionId, pi: data.pi, selector: params.selector, - sizes: bidRequest.sizes, + sizes: bidRequest.sizes || bidRequest.mediatype[banner].sizes, url: BID_ENDPOINT, method: 'GET', data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) @@ -221,7 +221,7 @@ function interpretResponse (serverResponse, bidRequest) { let [width, height] = sizes[0].split('x') // return 1x1 when breakout expected - if ((product === 2 || product === 5) && includes(sizes, '1x1')) { + if (product === 5 && includes(sizes, '1x1')) { width = '1' height = '1' } diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index a7a588afd13..53a6849fce3 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -245,8 +245,8 @@ describe('gumgumAdapter', function () { 'thms': 10000 } let result = spec.interpretResponse({ body: inscreenServerResponse }, inscreenBidRequest); - expect(result[0].width).to.equal('1'); - expect(result[0].height).to.equal('1'); + expect(result[0].width).to.equal(inscreenBidRequest.sizes[0][0].toString()); + expect(result[0].height).to.equal(inscreenBidRequest.sizes[0][1].toString()); }) }) describe('getUserSyncs', function () { From d813087887b48d37ad1c1182fca1c8c3675c4dcd Mon Sep 17 00:00:00 2001 From: christopher-allene-piximedia Date: Wed, 7 Aug 2019 15:57:58 +0200 Subject: [PATCH 148/436] Improve Piximedia Adapter (#4026) * Add Piximedia adapter * Add piximediaBidAdapter.md * Improve protocol of Piximedia bidder * Add Piximedia adapter * Fix piximediaBidAdapter_spec.js style * Fix Piximedia adapter * Revert "Fix Piximedia adapter" This reverts commit 10a10d6fbde61efe74f58539bdd9753f7048dd69. * Impprove Piximedia adapter * Remove CR at end of file * Add test for pbsizes in Piximedia adapter --- modules/piximediaBidAdapter.js | 1 + test/spec/modules/piximediaBidAdapter_spec.js | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/piximediaBidAdapter.js b/modules/piximediaBidAdapter.js index b97c91e5b5b..7fca4e32996 100644 --- a/modules/piximediaBidAdapter.js +++ b/modules/piximediaBidAdapter.js @@ -20,6 +20,7 @@ export const spec = { timestamp: utils.timestamp(), pver: '1.0', pbparams: JSON.stringify(bidRequest.params), + pbsizes: JSON.stringify(parseSized), pbwidth: arrSize[0], pbheight: arrSize[1], pbbidid: bidRequest.bidId, diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js index 02cf80c614f..95e03734345 100644 --- a/test/spec/modules/piximediaBidAdapter_spec.js +++ b/test/spec/modules/piximediaBidAdapter_spec.js @@ -47,6 +47,7 @@ describe('piximediaAdapterTest', function() { it('bidRequest data', function() { const requests = spec.buildRequests(bidRequests); expect(typeof requests[0].data.timestamp).to.equal('number'); + expect(requests[0].data.pbsizes).to.equal('["300x250"]'); expect(requests[0].data.pver).to.equal('1.0'); expect(requests[0].data.pbparams).to.equal(JSON.stringify(bidRequests[0].params)); expect(requests[0].data.pbwidth).to.equal('300'); From 5cfb75ea465797425c6c93ef47116ce69f08d8e3 Mon Sep 17 00:00:00 2001 From: rhythmonebhaines <49991465+rhythmonebhaines@users.noreply.github.com> Date: Wed, 7 Aug 2019 16:07:39 -0700 Subject: [PATCH 149/436] Rhythmone Adapter - deprecate direct usage of window objects. (#4061) --- modules/rhythmoneBidAdapter.js | 67 ++++++------- test/spec/modules/rhythmoneBidAdapter_spec.js | 97 ++++++++++++++++++- 2 files changed, 126 insertions(+), 38 deletions(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 84caca5508a..dc818e89f32 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -15,8 +15,7 @@ function RhythmOneBidAdapter() { let SUPPORTED_VIDEO_API = [1, 2, 5]; let slotsToBids = {}; let that = this; - let version = '2.0.1.0'; - var win = typeof window !== 'undefined' ? window : {}; + let version = '2.1'; this.isBidRequestValid = function (bid) { return !!(bid.params && bid.params.placementId); @@ -26,14 +25,21 @@ function RhythmOneBidAdapter() { return []; }; - function frameImp(BRs) { + function frameImp(BRs, bidderRequest) { var impList = []; + var isSecure = 0; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.stack.length) { + // clever trick to get the protocol + var el = document.createElement('a'); + el.href = bidderRequest.refererInfo.stack[0]; + isSecure = (el.protocol == 'https:') ? 1 : 0; + } for (var i = 0; i < BRs.length; i++) { - slotsToBids[BRs[i].adUnitCode || BRs[i].placementCode] = BRs[i]; + slotsToBids[BRs[i].adUnitCode] = BRs[i]; var impObj = {}; impObj.id = BRs[i].adUnitCode; impObj.bidfloor = parseFloat(utils.deepAccess(BRs[i], 'params.floor')) || 0; - impObj.secure = win.location.protocol === 'https:' ? 1 : 0; + impObj.secure = isSecure; if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { let banner = frameBanner(BRs[i]); @@ -54,31 +60,25 @@ function RhythmOneBidAdapter() { } function frameSite(bidderRequest) { - return { - domain: attempt(function() { - var d = win.document.location.ancestorOrigins; - if (d && d.length > 0) { - return d[d.length - 1]; - } - return win.top.document.location.hostname; // try/catch is in the attempt function - }, ''), - page: attempt(function() { - var l; - // try/catch is in the attempt function - try { - l = win.top.document.location.href.toString(); - } catch (ex) { - l = win.document.location.href.toString(); - } - return l; - }, ''), - ref: attempt(function() { - if (bidderRequest && bidderRequest.refererInfo) { - return bidderRequest.refererInfo.referer; - } - return ''; - }, '') + var site = { + domain: '', + page: '', + ref: '' } + if (bidderRequest && bidderRequest.refererInfo) { + var ri = bidderRequest.refererInfo; + site.ref = ri.referer; + + if (ri.stack.length) { + site.page = ri.stack[ri.stack.length - 1]; + + // clever trick to get the domain + var el = document.createElement('a'); + el.href = ri.stack[0]; + site.domain = el.hostname; + } + } + return site; } function frameDevice() { @@ -165,7 +165,7 @@ function RhythmOneBidAdapter() { function frameBid(BRs, bidderRequest) { return { id: BRs[0].bidderRequestId, - imp: frameImp(BRs), + imp: frameImp(BRs, bidderRequest), site: frameSite(bidderRequest), device: frameDevice(), user: { @@ -191,13 +191,6 @@ function RhythmOneBidAdapter() { } } - function attempt(valueFunction, defaultValue) { - try { - return valueFunction(); - } catch (ex) { } - return defaultValue; - } - this.buildRequests = function (BRs, bidderRequest) { let fallbackPlacementId = getFirstParam('placementId', BRs); if (fallbackPlacementId === undefined || BRs.length < 1) { diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index 6b414db47ab..b6ac09a6207 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -8,7 +8,11 @@ describe('rhythmone adapter tests', function () { beforeEach(function() { this.defaultBidderRequest = { 'refererInfo': { - 'referer': 'Reference Page' + 'referer': 'Reference Page', + 'stack': [ + 'aodomain.dvl', + 'page.dvl' + ] } }; }); @@ -611,6 +615,91 @@ describe('rhythmone adapter tests', function () { expect(bidRequest).to.be.empty; }); + + it('should return empty site data when refererInfo is missing', function() { + delete this.defaultBidderRequest.refererInfo; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.site.domain).to.equal(''); + expect(openrtbRequest.site.page).to.equal(''); + expect(openrtbRequest.site.ref).to.equal(''); + }); + }); + + it('should return empty site.domain and site.page when refererInfo.stack is empty', function() { + this.defaultBidderRequest.refererInfo.stack = []; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.site.domain).to.equal(''); + expect(openrtbRequest.site.page).to.equal(''); + expect(openrtbRequest.site.ref).to.equal('Reference Page'); + }); + + it('should secure correctly', function() { + this.defaultBidderRequest.refererInfo.stack[0] = ['https://securesite.dvl']; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.imp[0].secure).to.equal(1); }); describe('misc interpretResponse', function () { @@ -647,4 +736,10 @@ describe('rhythmone adapter tests', function () { expect(r1adapter.isBidRequestValid(bid)).to.equal(false); }); }); + + describe('getUserSyncs', function () { + it('returns an empty string', function () { + expect(r1adapter.getUserSyncs()).to.deep.equal([]); + }); + }); }); From afe18355a9672251bc5c3002caed21bf7d13c438 Mon Sep 17 00:00:00 2001 From: Benjamin Clot Date: Fri, 9 Aug 2019 05:02:12 +0200 Subject: [PATCH 150/436] Fix removeAdUnit (#4053) * Fix removeAdUnit When there are multiple adUnits with the same code, only one of them gets removed. This fixes that. * snapwich fix --- src/prebid.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/prebid.js b/src/prebid.js index 90f6365585e..efa1198d36c 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -390,12 +390,12 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { } adUnitCodes.forEach((adUnitCode) => { - for (let i = 0; i < $$PREBID_GLOBAL$$.adUnits.length; i++) { + for (let i = $$PREBID_GLOBAL$$.adUnits.length - 1; i >= 0; i--) { if ($$PREBID_GLOBAL$$.adUnits[i].code === adUnitCode) { $$PREBID_GLOBAL$$.adUnits.splice(i, 1); } } - }) + }); }; /** From 28cc013a6072858497698e7abf7926a0fae75845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20DEYM=C3=88S?= <47388595+MaxSmileWanted@users.noreply.github.com> Date: Fri, 9 Aug 2019 08:55:15 +0200 Subject: [PATCH 151/436] Adding support of Instream/Outstream Video for the SmileWanted Adapter (#4064) --- modules/smilewantedBidAdapter.js | 53 +++- modules/smilewantedBidAdapter.md | 40 +++ .../modules/smilewantedBidAdapter_spec.js | 246 ++++++++++++++---- 3 files changed, 280 insertions(+), 59 deletions(-) diff --git a/modules/smilewantedBidAdapter.js b/modules/smilewantedBidAdapter.js index bf9a75b6650..ed7e02a51a8 100644 --- a/modules/smilewantedBidAdapter.js +++ b/modules/smilewantedBidAdapter.js @@ -1,11 +1,13 @@ import * as utils from '../src/utils'; +import { Renderer } from '../src/Renderer'; import { config } from '../src/config'; import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; export const spec = { code: 'smilewanted', aliases: ['smile', 'sw'], - + supportedMediaTypes: [BANNER, VIDEO], /** * Determines whether or not the given bid request is valid. * @@ -65,6 +67,7 @@ export const spec = { interpretResponse: function(serverResponse, bidRequest) { const bidResponses = []; var response = serverResponse.body; + try { if (response) { const bidResponse = { @@ -77,10 +80,19 @@ export const spec = { currency: response.currency, netRevenue: response.isNetCpm, ttl: response.ttl, - adUrl: response.adUrl, - ad: response.ad + ad: response.ad, }; + if (response.formatTypeSw == 'video_instream' || response.formatTypeSw == 'video_outstream') { + bidResponse['mediaType'] = 'video'; + bidResponse['vastUrl'] = response.ad; + bidResponse['ad'] = null; + } + + if (response.formatTypeSw == 'video_outstream') { + bidResponse['renderer'] = newRenderer(JSON.parse(bidRequest.data), response); + } + bidResponses.push(bidResponse); } } catch (error) { @@ -110,4 +122,39 @@ export const spec = { } } +/** + * Create SmileWanted renderer + * @param requestId + * @returns {*} + */ +function newRenderer(bidRequest, bidResponse) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: bidResponse.OustreamTemplateUrl, + loaded: false + }); + + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on newRenderer', err); + } + return renderer; +} + +/** + * Initialise SmileWanted outstream + * @param bid + */ +function outstreamRender(bid) { + bid.renderer.push(() => { + window.SmileWantedOutStreamInit({ + width: bid.width, + height: bid.height, + vastUrl: bid.vastUrl, + elId: bid.adUnitCode + }); + }); +} + registerBidder(spec); diff --git a/modules/smilewantedBidAdapter.md b/modules/smilewantedBidAdapter.md index ddc25fe7456..678eda1eeee 100644 --- a/modules/smilewantedBidAdapter.md +++ b/modules/smilewantedBidAdapter.md @@ -13,6 +13,8 @@ To use us as a bidder you must have an account and an active "zoneId" on our Smi # Test Parameters ## Web + +### Display ``` var adUnits = [ { @@ -28,4 +30,42 @@ To use us as a bidder you must have an account and an active "zoneId" on our Smi ] } ]; +``` + +### Video Instream +``` + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'smilewanted', + params: { + zoneId: 2, + } + }] + }; +``` + +### Video Outstream +``` + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bids: [{ + bidder: 'smilewanted', + params: { + zoneId: 3, + } + }] + }; ``` \ No newline at end of file diff --git a/test/spec/modules/smilewantedBidAdapter_spec.js b/test/spec/modules/smilewantedBidAdapter_spec.js index 489f393523a..144c7ca60f6 100644 --- a/test/spec/modules/smilewantedBidAdapter_spec.js +++ b/test/spec/modules/smilewantedBidAdapter_spec.js @@ -5,62 +5,151 @@ import { config } from 'src/config'; import * as utils from 'src/utils'; import { requestBidsHook } from 'modules/consentManagement'; +const DISPLAY_REQUEST = [{ + adUnitCode: 'sw_300x250', + bidId: '12345', + sizes: [ + [300, 250], + [300, 200] + ], + bidder: 'smilewanted', + params: { + zoneId: 1, + bidfloor: 2.50 + }, + requestId: 'request_abcd1234', + transactionId: 'trans_abcd1234' +}]; + +const BID_RESPONSE_DISPLAY = { + body: { + cpm: 3, + width: 300, + height: 250, + creativeId: 'crea_sw_1', + currency: 'EUR', + isNetCpm: true, + ttl: 300, + ad: '< --- sw script --- >', + cSyncUrl: 'https://csync.smilewanted.com' + } +}; + +const VIDEO_INSTREAM_REQUEST = [{ + code: 'video1', + mediaTypes: { + video: {} + }, + sizes: [ + [640, 480] + ], + bidder: 'smilewanted', + params: { + zoneId: 2, + bidfloor: 2.50 + }, + requestId: 'request_abcd1234', + transactionId: 'trans_abcd1234' +}]; + +const BID_RESPONSE_VIDEO_INSTREAM = { + body: { + cpm: 3, + width: 640, + height: 480, + creativeId: 'crea_sw_2', + currency: 'EUR', + isNetCpm: true, + ttl: 300, + ad: 'https://vast.smilewanted.com', + cSyncUrl: 'https://csync.smilewanted.com', + formatTypeSw: 'video_instream' + } +}; + +const VIDEO_OUTSTREAM_REQUEST = [{ + code: 'video1', + mediaTypes: { + video: {} + }, + sizes: [ + [640, 480] + ], + bidder: 'smilewanted', + params: { + zoneId: 3, + bidfloor: 2.50 + }, + requestId: 'request_abcd1234', + transactionId: 'trans_abcd1234' +}]; + +const BID_RESPONSE_VIDEO_OUTSTREAM = { + body: { + cpm: 3, + width: 640, + height: 480, + creativeId: 'crea_sw_3', + currency: 'EUR', + isNetCpm: true, + ttl: 300, + ad: 'https://vast.smilewanted.com', + cSyncUrl: 'https://csync.smilewanted.com', + OustreamTemplateUrl: 'https://prebid.smilewanted.com/scripts_outstream/infeed.js', + formatTypeSw: 'video_outstream' + } +}; + // Default params with optional ones describe('smilewantedBidAdapterTests', function () { - var DEFAULT_PARAMS = [{ - adUnitCode: 'sw_300x250', - bidId: '12345', - sizes: [ - [300, 250], - [300, 200] - ], - bidder: 'smilewanted', - params: { - zoneId: '1234', - bidfloor: 2.50 - }, - requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234' - }]; - - var BID_RESPONSE = { - body: { - cpm: 3, - width: 300, - height: 250, - creativeId: 'crea_sw_1', - currency: 'EUR', - isNetCpm: true, - ttl: 300, - adUrl: 'https://www.smilewanted.com', - ad: '< --- sw script --- >', - cSyncUrl: 'https://csync.smilewanted.com' - } - }; - it('SmileWanted - Verify build request', function () { config.setConfig({ 'currency': { 'adServerCurrency': 'EUR' } }); - const request = spec.buildRequests(DEFAULT_PARAMS); - expect(request[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); - expect(request[0]).to.have.property('method').and.to.equal('POST'); - const requestContent = JSON.parse(request[0].data); - expect(requestContent).to.have.property('zoneId').and.to.equal('1234'); - expect(requestContent).to.have.property('currencyCode').and.to.equal('EUR'); - expect(requestContent).to.have.property('bidfloor').and.to.equal(2.50); - expect(requestContent).to.have.property('sizes'); - expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300); - expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250); - expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300); - expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200); - expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + + const requestDisplay = spec.buildRequests(DISPLAY_REQUEST); + expect(requestDisplay[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); + expect(requestDisplay[0]).to.have.property('method').and.to.equal('POST'); + const requestDisplayContent = JSON.parse(requestDisplay[0].data); + expect(requestDisplayContent).to.have.property('zoneId').and.to.equal(1); + expect(requestDisplayContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestDisplayContent).to.have.property('bidfloor').and.to.equal(2.50); + expect(requestDisplayContent).to.have.property('sizes'); + expect(requestDisplayContent.sizes[0]).to.have.property('w').and.to.equal(300); + expect(requestDisplayContent.sizes[0]).to.have.property('h').and.to.equal(250); + expect(requestDisplayContent.sizes[1]).to.have.property('w').and.to.equal(300); + expect(requestDisplayContent.sizes[1]).to.have.property('h').and.to.equal(200); + expect(requestDisplayContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + + const requestVideoInstream = spec.buildRequests(VIDEO_INSTREAM_REQUEST); + expect(requestVideoInstream[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); + expect(requestVideoInstream[0]).to.have.property('method').and.to.equal('POST'); + const requestVideoInstreamContent = JSON.parse(requestVideoInstream[0].data); + expect(requestVideoInstreamContent).to.have.property('zoneId').and.to.equal(2); + expect(requestVideoInstreamContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestVideoInstreamContent).to.have.property('bidfloor').and.to.equal(2.50); + expect(requestVideoInstreamContent).to.have.property('sizes'); + expect(requestVideoInstreamContent.sizes[0]).to.have.property('w').and.to.equal(640); + expect(requestVideoInstreamContent.sizes[0]).to.have.property('h').and.to.equal(480); + expect(requestVideoInstreamContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; + + const requestVideoOutstream = spec.buildRequests(VIDEO_OUTSTREAM_REQUEST); + expect(requestVideoOutstream[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com'); + expect(requestVideoOutstream[0]).to.have.property('method').and.to.equal('POST'); + const requestVideoOutstreamContent = JSON.parse(requestVideoOutstream[0].data); + expect(requestVideoOutstreamContent).to.have.property('zoneId').and.to.equal(3); + expect(requestVideoOutstreamContent).to.have.property('currencyCode').and.to.equal('EUR'); + expect(requestVideoOutstreamContent).to.have.property('bidfloor').and.to.equal(2.50); + expect(requestVideoOutstreamContent).to.have.property('sizes'); + expect(requestVideoOutstreamContent.sizes[0]).to.have.property('w').and.to.equal(640); + expect(requestVideoOutstreamContent.sizes[0]).to.have.property('h').and.to.equal(480); + expect(requestVideoOutstreamContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; }); it('SmileWanted - Verify build request with referrer', function () { - const request = spec.buildRequests(DEFAULT_PARAMS, { + const request = spec.buildRequests(DISPLAY_REQUEST, { refererInfo: { referer: 'http://localhost/Prebid.js/integrationExamples/gpt/hello_world.html' } @@ -87,7 +176,7 @@ describe('smilewantedBidAdapterTests', function () { allowAuctionWithoutConsent: true } }); - const request = spec.buildRequests(DEFAULT_PARAMS, { + const request = spec.buildRequests(DISPLAY_REQUEST, { gdprConsent: { consentString: 'BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA', gdprApplies: true @@ -110,7 +199,7 @@ describe('smilewantedBidAdapterTests', function () { allowAuctionWithoutConsent: true } }); - const request = spec.buildRequests(DEFAULT_PARAMS, { + const request = spec.buildRequests(DISPLAY_REQUEST, { gdprConsent: { consentString: 'BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA' } @@ -121,13 +210,12 @@ describe('smilewantedBidAdapterTests', function () { }); }); - it('SmileWanted - Verify parse response', function () { - const request = spec.buildRequests(DEFAULT_PARAMS); - const bids = spec.interpretResponse(BID_RESPONSE, request[0]); + it('SmileWanted - Verify parse response - Display', function () { + const request = spec.buildRequests(DISPLAY_REQUEST); + const bids = spec.interpretResponse(BID_RESPONSE_DISPLAY, request[0]); expect(bids).to.have.lengthOf(1); const bid = bids[0]; expect(bid.cpm).to.equal(3); - expect(bid.adUrl).to.equal('https://www.smilewanted.com'); expect(bid.ad).to.equal('< --- sw script --- >'); expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); @@ -135,10 +223,56 @@ describe('smilewantedBidAdapterTests', function () { expect(bid.currency).to.equal('EUR'); expect(bid.netRevenue).to.equal(true); expect(bid.ttl).to.equal(300); - expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId); + expect(bid.requestId).to.equal(DISPLAY_REQUEST[0].bidId); + + expect(function () { + spec.interpretResponse(BID_RESPONSE_DISPLAY, { + data: 'invalid Json' + }) + }).to.not.throw(); + }); + + it('SmileWanted - Verify parse response - Video Instream', function () { + const request = spec.buildRequests(VIDEO_INSTREAM_REQUEST); + const bids = spec.interpretResponse(BID_RESPONSE_VIDEO_INSTREAM, request[0]); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(3); + expect(bid.ad).to.equal(null); + expect(bid.vastUrl).to.equal('https://vast.smilewanted.com'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.creativeId).to.equal('crea_sw_2'); + expect(bid.currency).to.equal('EUR'); + expect(bid.netRevenue).to.equal(true); + expect(bid.ttl).to.equal(300); + expect(bid.requestId).to.equal(VIDEO_INSTREAM_REQUEST[0].bidId); + + expect(function () { + spec.interpretResponse(BID_RESPONSE_VIDEO_INSTREAM, { + data: 'invalid Json' + }) + }).to.not.throw(); + }); + + it('SmileWanted - Verify parse response - Video Oustream', function () { + const request = spec.buildRequests(VIDEO_OUTSTREAM_REQUEST); + const bids = spec.interpretResponse(BID_RESPONSE_VIDEO_OUTSTREAM, request[0]); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(3); + expect(bid.vastUrl).to.equal('https://vast.smilewanted.com'); + expect(bid.renderer.url).to.equal('https://prebid.smilewanted.com/scripts_outstream/infeed.js'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.creativeId).to.equal('crea_sw_3'); + expect(bid.currency).to.equal('EUR'); + expect(bid.netRevenue).to.equal(true); + expect(bid.ttl).to.equal(300); + expect(bid.requestId).to.equal(VIDEO_OUTSTREAM_REQUEST[0].bidId); expect(function () { - spec.interpretResponse(BID_RESPONSE, { + spec.interpretResponse(BID_RESPONSE_VIDEO_OUTSTREAM, { data: 'invalid Json' }) }).to.not.throw(); @@ -155,7 +289,7 @@ describe('smilewantedBidAdapterTests', function () { }); it('SmileWanted - Verify if bid request valid', function () { - expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true); + expect(spec.isBidRequestValid(DISPLAY_REQUEST[0])).to.equal(true); expect(spec.isBidRequestValid({ params: { zoneId: 1234 @@ -173,14 +307,14 @@ describe('smilewantedBidAdapterTests', function () { it('SmileWanted - Verify user sync', function () { var syncs = spec.getUserSyncs({ iframeEnabled: true - }, [BID_RESPONSE]); + }, [BID_RESPONSE_DISPLAY]); expect(syncs).to.have.lengthOf(1); expect(syncs[0].type).to.equal('iframe'); expect(syncs[0].url).to.equal('https://csync.smilewanted.com'); syncs = spec.getUserSyncs({ iframeEnabled: false - }, [BID_RESPONSE]); + }, [BID_RESPONSE_DISPLAY]); expect(syncs).to.have.lengthOf(0); syncs = spec.getUserSyncs({ From d1ed6e0abd320c95de7930645ec12af7cdb910b0 Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Fri, 9 Aug 2019 13:21:40 +0100 Subject: [PATCH 152/436] Fix for #4047 (#4063) * Changed isBidRequestValid to reject bid requests missing required parameters. * Filter outstream video bid requests. * Improved detection of different media types. Ignore all media types except instream video and banner. * Added test to confirm behaviour with multi-format request. * Removed unnecessary change to bid sizes. * Removed unused imports and tests. * Added log message for unsupported media types. --- modules/quantcastBidAdapter.js | 34 ++--- test/spec/modules/quantcastBidAdapter_spec.js | 131 +++++++++++------- 2 files changed, 100 insertions(+), 65 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 64cec7e231a..afe95ffb832 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -83,17 +83,7 @@ export const spec = { * @return boolean `true` is this is a valid bid, and `false` otherwise */ isBidRequestValid(bid) { - if (!bid) { - return false; - } - - const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (videoMediaType && context == 'outstream') { - return false; - } - - return true; + return !!bid.params.publisherId; }, /** @@ -112,12 +102,22 @@ export const spec = { const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); const domain = getDomain(page); - const bidRequestsList = bids.map(bid => { + let bidRequestsList = []; + + bids.forEach(bid => { let imp; - const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (videoContext === 'instream') { - imp = makeVideoImp(bid); + if (bid.mediaTypes) { + if (bid.mediaTypes.video && bid.mediaTypes.video.context === 'instream') { + imp = makeVideoImp(bid); + } else if (bid.mediaTypes.banner) { + imp = makeBannerImp(bid); + } else { + // Unsupported mediaType + utils.logInfo(`${BIDDER_CODE}: No supported mediaTypes found in ${JSON.stringify(bid.mediaTypes)}`); + return; + } } else { + // Parse as banner by default imp = makeBannerImp(bid); } @@ -143,11 +143,11 @@ export const spec = { : QUANTCAST_DOMAIN; const url = `${QUANTCAST_PROTOCOL}://${qcDomain}:${QUANTCAST_PORT}/qchb`; - return { + bidRequestsList.push({ data, method: 'POST', url - }; + }); }); return bidRequestsList; diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 662641de17b..e29a12a22be 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,6 +1,4 @@ -import * as utils from 'src/utils'; import { expect } from 'chai'; -import { stub, sandbox } from 'sinon'; import { QUANTCAST_DOMAIN, QUANTCAST_TEST_DOMAIN, @@ -13,11 +11,11 @@ import { } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; import { parse } from 'src/url'; -import * as ajax from 'src/ajax'; describe('Quantcast adapter', function () { const quantcastAdapter = newBidder(qcSpec); let bidRequest; + let bidderRequest; beforeEach(function () { bidRequest = { @@ -32,6 +30,13 @@ describe('Quantcast adapter', function () { }, sizes: [[300, 250]] }; + + bidderRequest = { + refererInfo: { + referer: 'http://example.com/hello.html', + canonicalUrl: 'http://example.com/hello.html' + } + }; }); function setupVideoBidRequest() { @@ -68,27 +73,25 @@ describe('Quantcast adapter', function () { }); describe('`isBidRequestValid`', function () { - it('should return `false` when bid is not passed', function () { - expect(qcSpec.isBidRequestValid()).to.equal(false); - }); - - it('should return `false` when bid is for outstream video', function () { + it('should return `true` when bid has publisherId', function () { const bidRequest = { - mediaType: 'video', - mediaTypes: { - video: { - context: 'outstream' - } + bidder: 'quantcast', + params: { + publisherId: 'my_publisher_id' } }; - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return `true` when bid contains required params', function () { - const bidRequest = { mediaType: 'banner' }; + it('should return `false` when bid has no publisherId', function () { + const bidRequest = { + bidder: 'quantcast', + params: { + } + }; - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); }); @@ -131,13 +134,6 @@ describe('Quantcast adapter', function () { }); it('sends banner bid requests contains all the required parameters', function () { - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/hello.html', - canonicalUrl: 'http://example.com/hello.html' - } - }; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedBannerBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, @@ -168,13 +164,6 @@ describe('Quantcast adapter', function () { it('sends video bid requests containing all the required parameters', function () { setupVideoBidRequest(); - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/hello.html', - canonicalUrl: 'http://example.com/hello.html' - } - }; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedVideoBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, @@ -213,6 +202,69 @@ describe('Quantcast adapter', function () { expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); }); + + it('ignores unsupported video bid requests', function () { + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [[550, 310]] + } + }; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + + expect(requests).to.be.empty; + }); + + it('parses multi-format bid request', function () { + bidRequest.mediaTypes = { + banner: {sizes: [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]}, + native: { + image: {required: true, sizes: [150, 50]}, + title: {required: true, len: 80}, + sponsoredBy: {required: true}, + clickUrl: {required: true}, + privacyLink: {required: false}, + body: {required: true}, + icon: {required: true, sizes: [50, 50]} + }, + video: { + context: 'outstream', + playerSize: [[550, 310]] + } + }; + bidRequest.sizes = [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedBidRequest = { + publisherId: QUANTCAST_TEST_PUBLISHER, + requestId: '2f7b179d443f14', + imp: [{ + banner: { + battr: [1, 2], + sizes: [ + {width: 300, height: 250}, + {width: 728, height: 90}, + {width: 250, height: 250}, + {width: 468, height: 60}, + {width: 320, height: 50} + ] + }, + placementCode: 'div-gpt-ad-1438287399331-0', + bidFloor: 1e-10 + }], + site: { + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' + }, + bidId: '2f7b179d443f14', + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); + }); }); it('propagates GDPR consent string and signal', function () { @@ -354,26 +406,9 @@ describe('Quantcast adapter', function () { body, headers: {} }; - const expectedResponse = []; const interpretedResponse = qcSpec.interpretResponse(response); expect(interpretedResponse.length).to.equal(0); }); }); - - // can't stub ajax with es6 anymore, need to fix this - // describe('`onTimeout`', function() { - // it('makes a request to the notify endpoint', function() { - // const sinonSandbox = sandbox.create(); - // const ajaxStub = sinonSandbox.stub(ajax, 'ajax').callsFake(function() {}); - // const timeoutData = { - // bidder: 'quantcast' - // }; - // qcSpec.onTimeout(timeoutData); - // const expectedUrl = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; - // ajaxStub.withArgs(expectedUrl, null, null).calledOnce.should.be.true; - // ajaxStub.restore(); - // sinonSandbox.restore(); - // }); - // }); }); From ceb4eff5db1fd2230d8dd0818d86cb1f8da141e3 Mon Sep 17 00:00:00 2001 From: Daniel McGraw Date: Fri, 9 Aug 2019 16:28:36 -0600 Subject: [PATCH 153/436] Clean up the 'Use case #2' example (#4068) --- modules/spotxBidAdapter.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/spotxBidAdapter.md b/modules/spotxBidAdapter.md index b9907e5bbd2..038c698a259 100644 --- a/modules/spotxBidAdapter.md +++ b/modules/spotxBidAdapter.md @@ -54,13 +54,12 @@ This adapter requires setup and approval from the SpotX team. ad_unit: 'outstream', outstream_options: { slot: 'adSlot1', - content_width: 300, - content_height: 250, custom_override: { // This option is not mandatory though used to override default renderer parameters using EASI player options in here: https://developer.spotxchange.com/content/local/docs/sdkDocs/EASI/README.md + content_width: 300, + content_height: 250, collapse: '1', hide_fullscreen: '1', unmute_on_mouse: '1', - click_to_replay: '1', continue_out_of_view: '1', ad_volume: '100', content_container_id: 'video1', From 65b07bb1947c80e105e987ee0c75cf82c714fa9d Mon Sep 17 00:00:00 2001 From: Debbie Wang Date: Sun, 11 Aug 2019 07:56:33 -0700 Subject: [PATCH 154/436] referer changes (#4072) --- modules/gumgumBidAdapter.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 75ba5da4de9..557e23254de 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -14,7 +14,7 @@ let browserParams = {}; let pageViewId = null // TODO: potential 0 values for browserParams sent to ad server -function _getBrowserParams() { +function _getBrowserParams(topWindowUrl) { let topWindow let topScreen let topUrl @@ -41,7 +41,7 @@ function _getBrowserParams() { try { topWindow = global.top; topScreen = topWindow.screen; - topUrl = utils.getTopWindowUrl() + topUrl = topWindowUrl || utils.getTopWindowUrl(); } catch (error) { utils.logError(error); return browserParams @@ -145,7 +145,8 @@ function buildRequests (validBidRequests, bidderRequest) { params = {}, transactionId } = bidRequest; - const data = {} + const data = {}; + const topWindowUrl = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; if (pageViewId) { data.pv = pageViewId } @@ -178,7 +179,7 @@ function buildRequests (validBidRequests, bidderRequest) { sizes: bidRequest.sizes || bidRequest.mediatype[banner].sizes, url: BID_ENDPOINT, method: 'GET', - data: Object.assign(data, _getBrowserParams(), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) + data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(), _getTradeDeskIDParam(bidRequest)) }) }); return bids; From fc360e5fe9e55f3b3a1678072b42c3298e2cc3d8 Mon Sep 17 00:00:00 2001 From: Samuel Horwitz Date: Sun, 11 Aug 2019 11:10:46 -0400 Subject: [PATCH 155/436] kargo adapter track request count (#4074) --- modules/kargoBidAdapter.js | 13 ++++++++++++- test/spec/modules/kargoBidAdapter_spec.js | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 74494ce66c9..7932822e90c 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -6,7 +6,9 @@ const HOST = 'https://krk.kargo.com'; const SYNC = 'https://crb.kargo.com/api/v1/initsyncrnd/{UUID}?seed={SEED}&idx={INDEX}'; const SYNC_COUNT = 5; -let sessionId; +let sessionId, + lastPageUrl, + requestCounter; export const spec = { code: BIDDER_CODE, @@ -31,6 +33,7 @@ export const spec = { } const transformedParams = Object.assign({}, { sessionId: spec._getSessionId(), + requestCount: spec._getRequestCount(), timeout: bidderRequest.timeout, currency: currency, cpmGranularity: 1, @@ -202,6 +205,14 @@ export const spec = { return sessionId; }, + _getRequestCount() { + if (lastPageUrl === window.location.pathname) { + return ++requestCounter; + } + lastPageUrl = window.location.pathname; + return requestCounter = 0; + }, + _generateRandomUuid() { try { // crypto.getRandomValues is supported everywhere but Opera Mini for years diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 7ff28a72c58..fd0e22b91b9 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -34,7 +34,7 @@ describe('kargo adapter tests', function () { }); describe('build request', function() { - var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = [], sessionIds = []; + var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = [], sessionIds = [], requestCount = 0; beforeEach(function () { undefinedCurrency = false; @@ -222,6 +222,7 @@ describe('kargo adapter tests', function () { function getExpectedKrakenParams(excludeUserIds, excludeKrux, expectedRawCRB, expectedRawCRBCookie) { var base = { timeout: 200, + requestCount: requestCount++, currency: 'USD', cpmGranularity: 1, timestamp: frozenNow.getTime(), From 11779127e9802d7bf02cb8f766afa094ec57a7be Mon Sep 17 00:00:00 2001 From: cdsmith16 <5227004+cdsmith16@users.noreply.github.com> Date: Sun, 11 Aug 2019 11:12:05 -0400 Subject: [PATCH 156/436] tlbidadapter missing semicolons (#4076) Fill in missing semicolons from TDID support update, which may be impacting TDID collection due to pb minification. Also updating for consistency with remainder of adapter. --- modules/tripleliftBidAdapter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index cd968475bd3..2d6b2dce8de 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -88,14 +88,14 @@ function _buildPostBody(bidRequests, bidderRequest) { banner: { format: _sizes(bid.sizes) } - } + }; }); - let eids = handleConsortiaUserIds(bidderRequest) + let eids = handleConsortiaUserIds(bidderRequest); if (eids.length > 0) { data.user = { ext: {eids} - } + }; } return data; @@ -126,7 +126,7 @@ function handleConsortiaUserIds(bidderRequest) { rtiPartner: 'TDID' } }] - }) + }); } return eids; From 87c9ba15904122014f4d34eca89e0256b1f4cae6 Mon Sep 17 00:00:00 2001 From: Michael Kuryshev Date: Sun, 11 Aug 2019 17:14:37 +0200 Subject: [PATCH 157/436] VIS.X adapter: don't use utils.getTopWindowUrl() (#4078) --- modules/visxBidAdapter.js | 18 ++++++++----- test/spec/modules/visxBidAdapter_spec.js | 34 ++++++++++++++---------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 740c08111bc..2f9ec73c569 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -67,7 +67,6 @@ export const spec = { }); const payload = { - u: utils.getTopWindowUrl(), pt: 'net', auids: auids.join(','), sizes: utils.getKeys(sizeMap).join(','), @@ -77,13 +76,18 @@ export const spec = { wrapperVersion: '$prebid.version$' }; - if (bidderRequest && bidderRequest.gdprConsent) { - if (bidderRequest.gdprConsent.consentString) { - payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + if (bidderRequest) { + if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + } + if (bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent.consentString) { + payload.gdpr_consent = bidderRequest.gdprConsent.consentString; + } + payload.gdpr_applies = + (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') + ? Number(bidderRequest.gdprConsent.gdprApplies) : 1; } - payload.gdpr_applies = - (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') - ? Number(bidderRequest.gdprConsent.gdprApplies) : 1; } return { diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index aa9b2b553ed..09ce92479f9 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -40,6 +40,12 @@ describe('VisxAdapter', function () { }); describe('buildRequests', function () { + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + const encodedReferrer = encodeURIComponent(bidderRequest.refererInfo.referer); let bidRequests = [ { 'bidder': 'visx', @@ -77,10 +83,10 @@ describe('VisxAdapter', function () { ]; it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]]); + const request = spec.buildRequests([bidRequests[0]], bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535'); expect(payload).to.have.property('sizes', '300x250,300x600'); @@ -89,10 +95,10 @@ describe('VisxAdapter', function () { }); it('sizes must not be duplicated', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -102,10 +108,10 @@ describe('VisxAdapter', function () { it('pt parameter must be "net" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -115,10 +121,10 @@ describe('VisxAdapter', function () { }); it('pt parameter must be "net" if params.priceType === "net"', function () { bidRequests[1].params.priceType = 'net'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -129,10 +135,10 @@ describe('VisxAdapter', function () { it('pt parameter must be "net" if params.priceType === "undefined"', function () { bidRequests[1].params.priceType = 'undefined'; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -144,10 +150,10 @@ describe('VisxAdapter', function () { it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -159,10 +165,10 @@ describe('VisxAdapter', function () { it('should add currency from currency.adServerCurrency', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u').that.is.a('string'); + expect(payload).to.have.property('u', encodedReferrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); From f49e4b14c35d0638ebf615d1370f5cd809014773 Mon Sep 17 00:00:00 2001 From: guiann Date: Sun, 11 Aug 2019 17:22:54 +0200 Subject: [PATCH 158/436] Multiple sizes handling in adYouLike adaptor (#4013) * Remove useless bidderCode in bid response * send all the available sizes in the bid request * Use the banner sizes if given * avoid compatibility issue with old bid format --- modules/adyoulikeBidAdapter.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index fd7a1697bac..12891b6e155 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -18,7 +18,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - const sizes = getSize(bid.sizes); + const sizes = getSize(getSizeArray(bid)); if (!bid.params || !bid.params.placement || !sizes.width || !sizes.height) { return false; } @@ -34,12 +34,14 @@ export const spec = { const payload = { Version: VERSION, Bids: bidRequests.reduce((accumulator, bid) => { - let size = getSize(bid.sizes); + let sizesArray = getSizeArray(bid); + let size = getSize(sizesArray); accumulator[bid.bidId] = {}; accumulator[bid.bidId].PlacementID = bid.params.placement; accumulator[bid.bidId].TransactionID = bid.transactionId; accumulator[bid.bidId].Width = size.width; accumulator[bid.bidId].Height = size.height; + accumulator[bid.bidId].AvaiableSizes = sizesArray.join(','); return accumulator; }, {}), PageRefreshed: getPageRefreshed() @@ -156,10 +158,20 @@ function createEndpointQS(bidderRequest) { return qs; } +function getSizeArray(bid) { + let inputSize = bid.sizes; + if (bid.mediaTypes && bid.mediaTypes.banner) { + inputSize = bid.mediaTypes.banner.sizes; + } + + return utils.parseSizesInput(inputSize); +} + /* Get parsed size from request size */ -function getSize(requestSizes) { +function getSize(sizesArray) { const parsed = {}; - const size = utils.parseSizesInput(requestSizes)[0]; + // the main requested size is the first one + const size = sizesArray[0]; if (typeof size !== 'string') { return parsed; From 5ff1fb6cecf73bb54ca75842db93b1ecf5273929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Mon, 12 Aug 2019 18:16:16 +0200 Subject: [PATCH 159/436] Criteo Adapter - Code cleaning & added missing tests to increase code coverage (#4073) --- modules/criteoBidAdapter.js | 79 ++++---- test/spec/modules/criteoBidAdapter_spec.js | 210 +++++++++++++++++++-- 2 files changed, 229 insertions(+), 60 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 56e22e45017..604278a14b9 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -8,15 +8,12 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -const ADAPTER_VERSION = 19; +export const ADAPTER_VERSION = 20; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; -const INTEGRATION_MODES = { - 'amp': 1, -}; const PROFILE_ID_INLINE = 207; -const PROFILE_ID_PUBLISHERTAG = 185; +export const PROFILE_ID_PUBLISHERTAG = 185; // Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js'; @@ -189,12 +186,12 @@ function buildContext(bidRequests) { url: url, debug: queryString['pbt_debug'] === '1', noLog: queryString['pbt_nolog'] === '1', - integrationMode: undefined, + amp: false, }; bidRequests.forEach(bidRequest => { - if (bidRequest.params.integrationMode) { - context.integrationMode = bidRequest.params.integrationMode; + if (bidRequest.params.integrationMode === 'amp') { + context.amp = true; } }) @@ -212,8 +209,8 @@ function buildCdbUrl(context) { url += '&wv=' + encodeURIComponent('$prebid.version$'); url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); - if (context.integrationMode in INTEGRATION_MODES) { - url += '&im=' + INTEGRATION_MODES[context.integrationMode]; + if (context.amp) { + url += '&im=1'; } if (context.debug) { url += '&debug=1'; @@ -382,47 +379,37 @@ function createNativeAd(id, payload, callback) { `; } -export function cryptoVerify(key, hash, code) { - var jse = new JSEncrypt(); - jse.setPublicKey(key); - return jse.verify(code, hash, sha256); -} - -function validateFastBid(fastBid) { - // The value stored must contain the file's encrypted hash as first line - const firstLineEnd = fastBid.indexOf('\n'); - const firstLine = fastBid.substr(0, firstLineEnd).trim(); - if (firstLine.substr(0, 9) !== '// Hash: ') { - utils.logWarn('No hash found in FastBid'); - return false; - } - - // Remove the hash part from the locally stored value - const fileEncryptedHash = firstLine.substr(9); - const publisherTag = fastBid.substr(firstLineEnd + 1); - - // Verify the hash using cryptography - try { - return cryptoVerify(FAST_BID_PUBKEY, fileEncryptedHash, publisherTag); - } catch (e) { - utils.logWarn('Failed to verify Criteo FastBid'); - return undefined; - } -} - /** * @return {boolean} */ -function tryGetCriteoFastBid() { +export function tryGetCriteoFastBid() { try { - const fastBid = localStorage.getItem('criteo_fast_bid'); - if (fastBid !== null) { - if (validateFastBid(fastBid) === false) { - utils.logWarn('Invalid Criteo FastBid found'); - localStorage.removeItem('criteo_fast_bid'); + const fastBidStorageKey = 'criteo_fast_bid'; + const hashPrefix = '// Hash: '; + const fastBidFromStorage = localStorage.getItem(fastBidStorageKey); + + if (fastBidFromStorage !== null) { + // The value stored must contain the file's encrypted hash as first line + const firstLineEndPosition = fastBidFromStorage.indexOf('\n'); + const firstLine = fastBidFromStorage.substr(0, firstLineEndPosition).trim(); + + if (firstLine.substr(0, hashPrefix.length) !== hashPrefix) { + utils.logWarn('No hash found in FastBid'); + localStorage.removeItem(fastBidStorageKey); } else { - utils.logInfo('Using Criteo FastBid'); - eval(fastBid); // eslint-disable-line no-eval + // Remove the hash part from the locally stored value + const publisherTagHash = firstLine.substr(hashPrefix.length); + const publisherTag = fastBidFromStorage.substr(firstLineEndPosition + 1); + + var jsEncrypt = new JSEncrypt(); + jsEncrypt.setPublicKey(FAST_BID_PUBKEY); + if (jsEncrypt.verify(publisherTag, publisherTagHash, sha256)) { + utils.logInfo('Using Criteo FastBid'); + eval(publisherTag); // eslint-disable-line no-eval + } else { + utils.logWarn('Invalid Criteo FastBid found'); + localStorage.removeItem(fastBidStorageKey); + } } } } catch (e) { diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 4fe60bba17c..a6ba642cb6d 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter'; +import { tryGetCriteoFastBid, spec, PROFILE_ID_PUBLISHERTAG, ADAPTER_VERSION, PUBLISHER_TAG_URL } from 'modules/criteoBidAdapter'; import { createBid } from 'src/bidfactory'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; @@ -7,9 +7,17 @@ import { config } from '../../../src/config'; import { VIDEO } from '../../../src/mediaTypes'; describe('The Criteo bidding adapter', function () { + let utilsMock; + beforeEach(function () { - // Remove FastBid to avoid side effects. + // Remove FastBid to avoid side effects localStorage.removeItem('criteo_fast_bid'); + utilsMock = sinon.mock(utils); + }); + + afterEach(function() { + global.Criteo = undefined; + utilsMock.restore(); }); describe('isBidRequestValid', function () { @@ -360,7 +368,8 @@ describe('The Criteo bidding adapter', function () { }); describe('buildRequests', function () { - const bidderRequest = { timeout: 3000, + const bidderRequest = { + timeout: 3000, gdprConsent: { gdprApplies: 1, consentString: 'concentDataString', @@ -377,6 +386,9 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a zoneId request', function () { + const publisherUrl = 'https://criteo.com?pbt_debug=1&pbt_nolog=1'; + utilsMock.expects('getTopWindowUrl').withExactArgs().once().returns(publisherUrl); + const bidRequests = [ { bidder: 'criteo', @@ -385,14 +397,17 @@ describe('The Criteo bidding adapter', function () { sizes: [[728, 90]], params: { zoneId: 123, + publisherSubId: '123', + nativeCallback: function() {}, + integrationMode: 'amp' }, }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d+&im=1&debug=1&nolog=1/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.url).to.equal(publisherUrl); expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); @@ -794,20 +809,187 @@ describe('The Criteo bidding adapter', function () { }); }); - describe('cryptoVerify', function () { - const TEST_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU='; + describe('tryGetCriteoFastBid', function () { + const VALID_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU='; + const INVALID_HASH = 'invalid'; + const VALID_PUBLISHER_TAG = 'test'; + const INVALID_PUBLISHER_TAG = 'test invalid'; + + const FASTBID_LOCAL_STORAGE_KEY = 'criteo_fast_bid'; + + it('should verify valid hash with valid publisher tag', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, '// Hash: ' + VALID_HASH + '\n' + VALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').once(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').never(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.equals('// Hash: ' + VALID_HASH + '\n' + VALID_PUBLISHER_TAG); + utilsMock.verify(); + }); + + it('should verify valid hash with invalid publisher tag', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, '// Hash: ' + VALID_HASH + '\n' + INVALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').once(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + + it('should verify invalid hash with valid publisher tag', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, '// Hash: ' + INVALID_HASH + '\n' + VALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').once(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + + it('should verify missing hash', function () { + localStorage.setItem(FASTBID_LOCAL_STORAGE_KEY, VALID_PUBLISHER_TAG); + + utilsMock.expects('logInfo').withExactArgs('Using Criteo FastBid').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in FastBid').once(); + utilsMock.expects('logWarn').withExactArgs('Invalid Criteo FastBid found').never(); + + tryGetCriteoFastBid(); + + expect(localStorage.getItem(FASTBID_LOCAL_STORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + }); + + describe('when pubtag prebid adapter is available', function () { + it('should forward response to pubtag when calling interpretResponse', () => { + const response = {}; + const request = {}; + + const adapter = { interpretResponse: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('interpretResponse').withExactArgs(response, request).once().returns('ok'); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(request).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; + + expect(spec.interpretResponse(response, request)).equal('ok'); + adapterMock.verify(); + prebidAdapterMock.verify(); + }); + + it('should forward bid to pubtag when calling onBidWon', () => { + const bid = { auctionId: 123 }; + + const adapter = { handleBidWon: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('handleBidWon').withExactArgs(bid).once(); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(bid.auctionId).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; - it('should verify right signature', function () { - expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test')).to.equal(true); + spec.onBidWon(bid); + adapterMock.verify(); + prebidAdapterMock.verify(); }); - it('should verify wrong signature', function () { - expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test wrong')).to.equal(false); + it('should forward bid to pubtag when calling onSetTargeting', () => { + const bid = { auctionId: 123 }; + + const adapter = { handleSetTargeting: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('handleSetTargeting').withExactArgs(bid).once(); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(bid.auctionId).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; + + spec.onSetTargeting(bid); + adapterMock.verify(); + prebidAdapterMock.verify(); }); - it('should return undefined with incompatible browsers', function () { - // Here use a null hash to make the call to crypto library fail and simulate a browser failure - expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.be.false; + it('should forward bid to pubtag when calling onTimeout', () => { + const timeoutData = { auctionId: 123 }; + + const adapter = { handleBidTimeout: function() {} }; + const adapterMock = sinon.mock(adapter); + adapterMock.expects('handleBidTimeout').once(); + const prebidAdapter = { GetAdapter: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('GetAdapter').withExactArgs(timeoutData.auctionId).once().returns(adapter); + + global.Criteo = { + PubTag: { + Adapters: { + Prebid: prebidAdapter + } + } + }; + + spec.onTimeout(timeoutData); + adapterMock.verify(); + prebidAdapterMock.verify(); + }); + + it('should return a POST method with url & data from pubtag', () => { + const bidRequests = { }; + const bidderRequest = { }; + + const prebidAdapter = { buildCdbUrl: function() {}, buildCdbRequest: function() {} }; + const prebidAdapterMock = sinon.mock(prebidAdapter); + prebidAdapterMock.expects('buildCdbUrl').once().returns('cdbUrl'); + prebidAdapterMock.expects('buildCdbRequest').once().returns('cdbRequest'); + + const adapters = { Prebid: function() {} }; + const adaptersMock = sinon.mock(adapters); + adaptersMock.expects('Prebid').withExactArgs(PROFILE_ID_PUBLISHERTAG, ADAPTER_VERSION, bidRequests, bidderRequest, '$prebid.version$').once().returns(prebidAdapter); + + global.Criteo = { + PubTag: { + Adapters: adapters + } + }; + + const buildRequestsResult = spec.buildRequests(bidRequests, bidderRequest); + expect(buildRequestsResult.method).equal('POST'); + expect(buildRequestsResult.url).equal('cdbUrl'); + expect(buildRequestsResult.data).equal('cdbRequest'); + + adaptersMock.verify(); + prebidAdapterMock.verify(); }); }); }); From e636efe2221c5521ef80e4fce3a9da208d37c791 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Tue, 13 Aug 2019 06:30:25 -0600 Subject: [PATCH 160/436] update to use dlv/index to fix webpack sourcemaps (#4071) --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 6f592a8bcfe..335cf8dbf68 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,7 +5,7 @@ import includes from 'core-js/library/fn/array/includes'; import { parse } from './url'; const CONSTANTS = require('./constants'); -export { default as deepAccess } from 'dlv'; +export { default as deepAccess } from 'dlv/index'; export { default as deepSetValue } from 'dset'; var tArr = 'Array'; From 1224e50128b868100b70656904c0d1a73f949e11 Mon Sep 17 00:00:00 2001 From: Elber Carneiro Date: Tue, 13 Aug 2019 13:34:15 -0400 Subject: [PATCH 161/436] Yieldmo unified id (#4041) * update maintainer email * Add TTD unified id * Remove console.log * Remove trailing spaces --- modules/yieldmoBidAdapter.js | 22 ++++++++++++----- modules/yieldmoBidAdapter.md | 1 - test/spec/modules/yieldmoBidAdapter_spec.js | 26 +++++++++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 299baf49042..fd09cbaa4ea 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -43,7 +43,7 @@ export const spec = { bidRequests.forEach((request) => { serverRequest.p.push(addPlacement(request)); - const pubcid = getPubcId(request) + const pubcid = getId(request, 'pubcid'); if (pubcid) { serverRequest.pubcid = pubcid; } else if (request.crumbs) { @@ -51,6 +51,10 @@ export const spec = { serverRequest.pubcid = request.crumbs.pubcid; } } + const tdid = getId(request, 'tdid'); + if (tdid) { + serverRequest.tdid = tdid; + } }); serverRequest.p = '[' + serverRequest.p.toString() + ']'; return { @@ -317,10 +321,16 @@ function isMraid() { return !!(window.mraid); } -function getPubcId(request) { - let pubcid; - if (request && request.userId && request.userId.pubcid && typeof request.userId === 'object') { - pubcid = request.userId.pubcid; +/** + * Gets an id from the userId object if it exists + * @param {*} request + * @param {*} idType + * @returns an id if there is one, or undefined + */ +function getId(request, idType) { + let id; + if (request && request.userId && request.userId[idType] && typeof request.userId === 'object') { + id = request.userId[idType]; } - return pubcid; + return id; } diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index 7221f2ebdd0..d1e34a41ecb 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -4,7 +4,6 @@ Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter Maintainer: opensource@yieldmo.com -Note: Our ads will only render in mobile ``` # Description diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 2a94dc7e5c9..60fe25db95e 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -7,6 +7,8 @@ describe('YieldmoAdapter', function () { const adapter = newBidder(spec); const ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; + let tdid = '8d146286-91d4-4958-aff4-7e489dd1abd6'; + let bid = { bidder: 'yieldmo', params: { @@ -19,6 +21,9 @@ describe('YieldmoAdapter', function () { auctionId: '1d1a030790a475', crumbs: { pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + }, + userId: { + tdid, } }; let bidArray = [bid]; @@ -109,7 +114,7 @@ describe('YieldmoAdapter', function () { expect(data.hasOwnProperty('h')).to.be.true; expect(data.hasOwnProperty('w')).to.be.true; expect(data.hasOwnProperty('pubcid')).to.be.true; - }) + }); it('should add pubcid as parameter of request', function () { const pubcidBid = { @@ -126,7 +131,24 @@ describe('YieldmoAdapter', function () { }; const data = spec.buildRequests([pubcidBid]).data; expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); - }) + }); + + it('should add unified id as parameter of request', function () { + const unifiedIdBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + tdid, + } + }; + const data = spec.buildRequests([unifiedIdBid]).data; + expect(data.tdid).to.deep.equal(tdid); + }); }); describe('interpretResponse', function () { From aee906b7b345574cc2bb8b71e4f8ceec57a83b2d Mon Sep 17 00:00:00 2001 From: "Evgen A. Epanchin" Date: Tue, 13 Aug 2019 23:42:06 +0300 Subject: [PATCH 162/436] Add video support to LoopMe adapter (#4079) --- modules/loopmeBidAdapter.js | 64 ++++++++++++-- modules/loopmeBidAdapter.md | 21 ++++- test/spec/modules/loopmeBidAdapter_spec.js | 98 ++++++++++++++++++---- 3 files changed, 158 insertions(+), 25 deletions(-) diff --git a/modules/loopmeBidAdapter.js b/modules/loopmeBidAdapter.js index fcfe1fd0687..dd0c7e38553 100644 --- a/modules/loopmeBidAdapter.js +++ b/modules/loopmeBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; -import { BANNER } from '../src/mediaTypes'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import { Renderer } from '../src/Renderer'; const LOOPME_ENDPOINT = 'https://loopme.me/api/hb'; @@ -16,7 +17,7 @@ const entries = (obj) => { export const spec = { code: 'loopme', - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, VIDEO], /** * @param {object} bid * @return boolean @@ -46,14 +47,17 @@ export const spec = { .map(item => `${item[0]}=${encodeURI(item[1])}`) .join('&'); + const adUnitSizes = bidRequest.mediaTypes[BANNER] + ? utils.getAdUnitSizes(bidRequest) + : utils.deepAccess(bidRequest.mediaTypes, 'video.playerSize'); + const sizes = '&sizes=' + - utils - .getAdUnitSizes(bidRequest) + adUnitSizes .map(size => `${size[0]}x${size[1]}`) .join('&sizes='); - queryString = `${queryString}${sizes}`; + queryString = `${queryString}${sizes}${bidRequest.mediaTypes[VIDEO] ? '&media_type=video' : ''}`; return { method: 'GET', @@ -71,14 +75,58 @@ export const spec = { */ interpretResponse: function(response = {}, bidRequest) { const responseObj = response.body; + if ( + responseObj === null || + typeof responseObj !== 'object' + ) { + return []; + } if ( - responseObj == null || - typeof responseObj !== 'object' || - !responseObj.hasOwnProperty('ad') + !responseObj.hasOwnProperty('ad') && + !responseObj.hasOwnProperty('vastUrl') ) { return []; } + // responseObj.vastUrl = 'https://rawgit.com/InteractiveAdvertisingBureau/VAST_Samples/master/VAST%201-2.0%20Samples/Inline_NonLinear_Verification_VAST2.0.xml'; + if (responseObj.vastUrl) { + const renderer = Renderer.install({ + id: bidRequest.bidId, + url: 'https://i.loopme.me/html/vast/loopme_flex.js', + loaded: false + }); + renderer.setRender((bid) => { + renderer.push(function () { + var adverts = [{ + 'type': 'VAST', + 'url': bid.vastUrl, + 'autoClose': -1 + }]; + var config = { + containerId: bid.adUnitCode, + vastTimeout: 250, + ads: adverts, + user_consent: '%%USER_CONSENT%%', + }; + window.L.flex.loader.load(config); + }) + }); + return [ + { + requestId: bidRequest.bidId, + cpm: responseObj.cpm, + width: responseObj.width, + height: responseObj.height, + ttl: responseObj.ttl, + currency: responseObj.currency, + creativeId: responseObj.creativeId, + dealId: responseObj.dealId, + netRevenue: responseObj.netRevenue, + vastUrl: responseObj.vastUrl, + renderer + } + ]; + } return [ { diff --git a/modules/loopmeBidAdapter.md b/modules/loopmeBidAdapter.md index be8c20cfade..1b195a118f2 100644 --- a/modules/loopmeBidAdapter.md +++ b/modules/loopmeBidAdapter.md @@ -10,7 +10,7 @@ Maintainer: support@loopme.com Connect to LoopMe's exchange for bids. -# Test Parameters +# Test Parameters (Banner) ``` var adUnits = [{ code: 'test-div', @@ -27,3 +27,22 @@ var adUnits = [{ }] }]; ``` + +# Test Parameters (Video) +``` +var adUnits = [{ + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream' + } + }, + bids: [{ + bidder: 'loopme', + params: { + ak: '223051e07f' + } + }] +}]; +``` diff --git a/test/spec/modules/loopmeBidAdapter_spec.js b/test/spec/modules/loopmeBidAdapter_spec.js index 6d612746299..0d7e71c22db 100644 --- a/test/spec/modules/loopmeBidAdapter_spec.js +++ b/test/spec/modules/loopmeBidAdapter_spec.js @@ -15,37 +15,71 @@ describe('LoopMeAdapter', function () { }, adUnitCode: 'ad-1', bidId: '2652ca954bce9' - }]; + }, { + bidder: 'loopme', + params: { + ak: 'b510d5bcda' + }, + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'outstream' + } + }, + adUnitCode: 'ad-1', + bidId: '2652ca954bce9' + } + ]; describe('isBidRequestValid', function () { it('should return true if the ak parameter is present', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; + expect(spec.isBidRequestValid(bidRequests[1])).to.be.true; }); it('should return false if the ak parameter is not present', function () { - let bidRequest = utils.deepClone(bidRequests[0]); - delete bidRequest.params.ak; - expect(spec.isBidRequestValid(bidRequest)).to.be.false; + let bannerBidRequest = utils.deepClone(bidRequests[0]); + delete bannerBidRequest.params.ak; + expect(spec.isBidRequestValid(bannerBidRequest)).to.be.false; + + let videoBidRequest = utils.deepClone(bidRequests[1]); + delete videoBidRequest.params.ak; + expect(spec.isBidRequestValid(videoBidRequest)).to.be.false; }); it('should return false if the params object is not present', function () { - let bidRequest = utils.deepClone(bidRequests); - delete bidRequest[0].params; - expect(spec.isBidRequestValid(bidRequest)).to.be.false; + let bannerBidRequest = utils.deepClone(bidRequests)[0]; + delete bannerBidRequest.params; + expect(spec.isBidRequestValid(bannerBidRequest)).to.be.false; + + let videoBidRequest = utils.deepClone(bidRequests)[1]; + delete videoBidRequest.params; + expect(spec.isBidRequestValid(videoBidRequest)).to.be.false; }); }); describe('buildRequests', function () { it('should generate a valid single GET request for multiple bid requests', function () { - const request = spec.buildRequests(bidRequests)[0]; - expect(request.method).to.equal('GET'); - expect(request.url).to.equal('https://loopme.me/api/hb'); - expect(request.bidId).to.equal('2652ca954bce9'); - expect(request.data).to.exist; + const bannerRequest = spec.buildRequests(bidRequests)[0]; + expect(bannerRequest.method).to.equal('GET'); + expect(bannerRequest.url).to.equal('https://loopme.me/api/hb'); + expect(bannerRequest.bidId).to.equal('2652ca954bce9'); + expect(bannerRequest.data).to.exist; - const requestData = request.data; - expect(requestData).to.contain('ak=b510d5bcda'); - expect(requestData).to.contain('sizes=300x250'); + const bannerRequestData = bannerRequest.data; + expect(bannerRequestData).to.contain('ak=b510d5bcda'); + expect(bannerRequestData).to.contain('sizes=300x250'); + + const videoRequest = spec.buildRequests(bidRequests)[1]; + expect(videoRequest.method).to.equal('GET'); + expect(videoRequest.url).to.equal('https://loopme.me/api/hb'); + expect(videoRequest.bidId).to.equal('2652ca954bce9'); + expect(videoRequest.data).to.exist; + + const videoRquestData = videoRequest.data; + expect(videoRquestData).to.contain('ak=b510d5bcda'); + expect(videoRquestData).to.contain('sizes=640x480'); + expect(videoRquestData).to.contain('media_type=video'); }); it('should add GDPR data to request if available', function () { @@ -67,7 +101,7 @@ describe('LoopMeAdapter', function () { expect(interpretedResponse).to.be.an('array').that.is.empty; }); - it('should return valid response when passed valid server response', function () { + xit('should return valid response when passed valid server response', function () { const serverResponse = { body: { 'requestId': '2652ca954bce9', @@ -97,5 +131,37 @@ describe('LoopMeAdapter', function () { expect(interpretedResponse[0].ad).to.equal(serverResponse.body.ad); expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.ttl); }); + + it('should return valid VAST response when passed valid server response', function () { + const serverResponse = { + body: { + 'requestId': '2652ca954bce9', + 'cpm': 1, + 'width': 640, + 'height': 480, + 'creativeId': '20154', + 'currency': 'USD', + 'netRevenue': false, + 'ttl': 360, + 'vastUrl': 'https://loopme.me/ads/vast?ak=cc885e3acc' + } + }; + + const request = spec.buildRequests(bidRequests)[1]; + const interpretedResponse = spec.interpretResponse(serverResponse, request); + + expect(interpretedResponse).to.have.lengthOf(1); + + expect(interpretedResponse[0].requestId).to.equal(serverResponse.body.requestId); + expect(interpretedResponse[0].cpm).to.equal(serverResponse.body.cpm); + expect(interpretedResponse[0].width).to.equal(serverResponse.body.width); + expect(interpretedResponse[0].height).to.equal(serverResponse.body.height); + expect(interpretedResponse[0].creativeId).to.equal(serverResponse.body.creativeId); + expect(interpretedResponse[0].currency).to.equal(serverResponse.body.currency); + expect(interpretedResponse[0].netRevenue).to.equal(serverResponse.body.netRevenue); + expect(interpretedResponse[0].vastUrl).to.equal(serverResponse.body.vastUrl); + expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.ttl); + expect(interpretedResponse[0].renderer).to.have.property('render'); + }); }); }); From 5c2fb9ee2d26855ff4cc4b4d4dcae147f9269973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9onard=20Labat?= Date: Thu, 15 Aug 2019 17:34:05 +0200 Subject: [PATCH 163/436] Criteo Adapter - Added support of deals (#4085) --- modules/criteoBidAdapter.js | 1 + test/spec/modules/criteoBidAdapter_spec.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 604278a14b9..559c02cd4a9 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -120,6 +120,7 @@ export const spec = { creativeId: bidId, width: slot.width, height: slot.height, + dealId: slot.dealCode, } if (slot.native) { bid.ad = createNativeAd(bidId, slot.native, bidRequest.params.nativeCallback); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index a6ba642cb6d..f85e5957950 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -656,6 +656,7 @@ describe('The Criteo bidding adapter', function () { creative: 'test-ad', width: 728, height: 90, + dealCode: 'myDealCode', }], }, }; @@ -675,6 +676,7 @@ describe('The Criteo bidding adapter', function () { expect(bids[0].ad).to.equal('test-ad'); expect(bids[0].width).to.equal(728); expect(bids[0].height).to.equal(90); + expect(bids[0].dealId).to.equal('myDealCode'); }); it('should properly parse a bid responsewith with a zoneId', function () { From 247609648a36f647f69d21be358d29f0ed33025a Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 15 Aug 2019 14:06:11 -0400 Subject: [PATCH 164/436] 2.28.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8062204ce1..1a9547a3da2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.28.0-pre", + "version": "2.28.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 598da43b23df08cf85524401a9aa3d2e5cc4941e Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Thu, 15 Aug 2019 14:16:07 -0400 Subject: [PATCH 165/436] 2.29.0-pre --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a9547a3da2..da9bdf63507 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.28.0", + "version": "2.29.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 0014fa4fe786646ed28fcf870ab89a9eb1eabf24 Mon Sep 17 00:00:00 2001 From: SublimeJeremy Date: Fri, 16 Aug 2019 19:53:17 +0200 Subject: [PATCH 166/436] Add bid adapter for Sublime (#3960) * Add bid adapter for Sublime * Fix tests for sublimeBidAdapter * Fix tests for sublimeBidAdapter * fix(sublime-adapter): fixes to submit sublimePrebidAdapter * fix(sublime-adapter): fixes to submit sublimePrebidAdapter * Remove callback and fix tests * Update adapter to version 0.4.0 - Support of multiple bid request - Remove pixel call - Remove tag - Refactor - Update test * Rearrange constant and import alphabetically * sublimeBidAdapter: remove deprecated method getTopWindowUrl --- modules/sublimeBidAdapter.js | 135 +++++++++++ modules/sublimeBidAdapter.md | 62 +++++ test/spec/modules/sublimeBidAdapter_spec.js | 255 ++++++++++++++++++++ 3 files changed, 452 insertions(+) create mode 100644 modules/sublimeBidAdapter.js create mode 100644 modules/sublimeBidAdapter.md create mode 100644 test/spec/modules/sublimeBidAdapter_spec.js diff --git a/modules/sublimeBidAdapter.js b/modules/sublimeBidAdapter.js new file mode 100644 index 00000000000..fce3df7675b --- /dev/null +++ b/modules/sublimeBidAdapter.js @@ -0,0 +1,135 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; + +const BIDDER_CODE = 'sublime'; +const DEFAULT_BID_HOST = 'pbjs.sskzlabs.com'; +const DEFAULT_CURRENCY = 'EUR'; +const DEFAULT_PROTOCOL = 'https'; +const DEFAULT_TTL = 600; +const SUBLIME_VERSION = '0.4.0'; + +export const spec = { + code: BIDDER_CODE, + aliases: [], + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: (bid) => { + return !!bid.params.zoneId; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests An array of bids + * @param {Object} bidderRequest - Info describing the request to the server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests, bidderRequest) => { + let commonPayload = { + sublimeVersion: SUBLIME_VERSION, + // Current Prebid params + prebidVersion: '$prebid.version$', + currencyCode: config.getConfig('currency.adServerCurrency') || DEFAULT_CURRENCY, + timeout: config.getConfig('bidderTimeout'), + }; + + // RefererInfo + if (bidderRequest && bidderRequest.refererInfo) { + commonPayload.referer = bidderRequest.refererInfo.referer; + commonPayload.numIframes = bidderRequest.refererInfo.numIframes; + } + // GDPR handling + if (bidderRequest && bidderRequest.gdprConsent) { + commonPayload.gdprConsent = bidderRequest.gdprConsent.consentString; + commonPayload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side + } + + return validBidRequests.map(bid => { + let bidPayload = { + adUnitCode: bid.adUnitCode, + auctionId: bid.auctionId, + bidder: bid.bidder, + bidderRequestId: bid.bidderRequestId, + bidRequestsCount: bid.bidRequestsCount, + requestId: bid.bidId, + sizes: bid.sizes.map(size => ({ + w: size[0], + h: size[1], + })), + transactionId: bid.transactionId, + zoneId: bid.params.zoneId, + }; + + let protocol = bid.params.protocol || DEFAULT_PROTOCOL; + let bidHost = bid.params.bidHost || DEFAULT_BID_HOST; + let payload = Object.assign({}, commonPayload, bidPayload); + + return { + method: 'POST', + url: protocol + '://' + bidHost + '/bid', + data: payload, + options: { + contentType: 'application/json', + withCredentials: true + }, + }; + }); + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @param {*} bidRequest An object with bid request informations + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: (serverResponse, bidRequest) => { + const bidResponses = []; + const response = serverResponse.body; + + if (response) { + if (response.timeout || !response.ad || response.ad.match(//gmi)) { + return bidResponses; + } + + // Setting our returned sizes object to default values + let returnedSizes = { + width: 1800, + height: 1000 + }; + + // Verifying Banner sizes + if (bidRequest && bidRequest.data && bidRequest.data.w === 1 && bidRequest.data.h === 1) { + // If banner sizes are 1x1 we set our default size object to 1x1 + returnedSizes = { + width: 1, + height: 1 + }; + } + + const bidResponse = { + requestId: response.requestId || '', + cpm: response.cpm || 0, + width: response.width || returnedSizes.width, + height: response.height || returnedSizes.height, + creativeId: response.creativeId || 1, + dealId: response.dealId || 1, + currency: response.currency || DEFAULT_CURRENCY, + netRevenue: response.netRevenue || true, + ttl: response.ttl || DEFAULT_TTL, + ad: response.ad, + }; + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, +}; + +registerBidder(spec); diff --git a/modules/sublimeBidAdapter.md b/modules/sublimeBidAdapter.md new file mode 100644 index 00000000000..e57f4a1fdb0 --- /dev/null +++ b/modules/sublimeBidAdapter.md @@ -0,0 +1,62 @@ +# Overview + +``` +Module Name: Sublime Bid Adapter +Module Type: Bidder Adapter +Maintainer: pbjs@sublimeskinz.com +``` + +# Description + +Connects to Sublime for bids. +Sublime bid adapter supports Skinz and M-Skinz formats. + +# Nota Bene + +Our prebid adapter is unusable with SafeFrame. + +# Build + +You can build your version of prebid.js, execute: + +```shell +gulp build --modules=sublimeBidAdapter +``` + +Or to build with multiple adapters + +```shell +gulp build --modules=sublimeBidAdapter,secondAdapter,thirdAdapter +``` + +More details in the root [README](../README.md#Build) + +## To build from you own repository + +- copy `/modules/sublimeBidAdapter.js` to your `/modules/` directory +- copy `/modules/sublimeBidAdapter.md` to your `/modules/` directory +- copy `/test/spec/modules/sublimeBidAdapter_spec.js` to your `/test/spec/modules/` directory + +Then build + + +# Invocation Parameters + +```js +var adUnits = [{ + code: 'sublime', + mediaTypes: { + banner: { + sizes: [1800, 1000] + } + }, + bids: [{ + bidder: 'sublime', + params: { + zoneId: + } + }] +}]; +``` + +Where you replace `` by your Sublime Zone id diff --git a/test/spec/modules/sublimeBidAdapter_spec.js b/test/spec/modules/sublimeBidAdapter_spec.js new file mode 100644 index 00000000000..45173b09953 --- /dev/null +++ b/test/spec/modules/sublimeBidAdapter_spec.js @@ -0,0 +1,255 @@ +import { expect } from 'chai'; +import { spec } from 'modules/sublimeBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +describe('Sublime Adapter', function() { + const adapter = newBidder(spec); + + describe('inherited functions', function() { + it('exists and is a function', function() { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function() { + let bid = { + bidder: 'sublime', + params: { + zoneId: 24549, + endpoint: '', + }, + }; + + it('should return true when required params found', function() { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function() { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function() { + let bidRequests = [ + { + bidder: 'sublime', + adUnitCode: 'sublime_code', + bidId: 'abc1234', + sizes: [[1800, 1000], [640, 300]], + requestId: 'xyz654', + params: { + zoneId: 123, + callbackName: 'false' + } + }, { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + sizes: [[1, 1]], + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + } + ]; + + let bidderRequest = { + gdprConsent: { + consentString: 'EOHEIRCOUCOUIEHZIOEIU-TEST', + gdprApplies: true + }, + refererInfo: { + referer: 'https://example.com', + numIframes: 2, + } + }; + + let request = spec.buildRequests(bidRequests, bidderRequest); + + it('should have a post method', function() { + expect(request[0].method).to.equal('POST'); + expect(request[1].method).to.equal('POST'); + }); + + it('should contains a request id equals to the bid id', function() { + expect(request[0].data.requestId).to.equal(bidRequests[0].bidId); + expect(request[1].data.requestId).to.equal(bidRequests[1].bidId); + }); + + it('should have an url that contains bid keyword', function() { + expect(request[0].url).to.match(/bid/); + expect(request[1].url).to.match(/bid/); + }); + }); + + describe('buildRequests: default arguments', function() { + let bidRequests = [{ + bidder: 'sublime', + adUnitCode: 'sublime_code', + bidId: 'abc1234', + sizes: [[1800, 1000], [640, 300]], + requestId: 'xyz654', + params: { + zoneId: 123 + } + }]; + + let request = spec.buildRequests(bidRequests); + + it('should have an url that match the default endpoint', function() { + expect(request[0].url).to.equal('https://pbjs.sskzlabs.com/bid'); + }); + }); + + describe('interpretResponse', function() { + let serverResponse = { + 'request_id': '3db3773286ee59', + 'cpm': 0.5, + 'ad': '', + }; + + it('should get correct bid response', function() { + // Mock the fire method + top.window.sublime = { + analytics: { + fire: function() {} + } + }; + + let expectedResponse = [ + { + requestId: '', + cpm: 0.5, + width: 1800, + height: 1000, + creativeId: 1, + dealId: 1, + currency: 'USD', + netRevenue: true, + ttl: 600, + ad: '', + }, + ]; + let result = spec.interpretResponse({body: serverResponse}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should get correct default size for 1x1', function() { + let serverResponse = { + 'requestId': 'xyz654_2', + 'cpm': 0.5, + 'ad': '', + }; + + let bidRequest = { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + data: { + w: 1, + h: 1, + }, + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + }; + + let result = spec.interpretResponse({body: serverResponse}, bidRequest); + + let expectedResponse = { + requestId: 'xyz654_2', + cpm: 0.5, + width: 1, + height: 1, + creativeId: 1, + dealId: 1, + currency: 'EUR', + netRevenue: true, + ttl: 600, + ad: '', + }; + + expect(result[0]).to.deep.equal(expectedResponse); + }); + + it('should return bid empty response', function () { + let serverResponse = ''; + let bidRequest = {}; + + let result = spec.interpretResponse({ body: serverResponse }, bidRequest); + + let expectedResponse = []; + + expect(result).to.deep.equal(expectedResponse); + }); + + it('should return bid with default value in response', function () { + let serverResponse = { + 'requestId': 'xyz654_2', + 'ad': '', + }; + + let bidRequest = { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + data: { + w: 1, + h: 1, + }, + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + }; + + let result = spec.interpretResponse({ body: serverResponse }, bidRequest); + + let expectedResponse = { + requestId: 'xyz654_2', + cpm: 0, + width: 1, + height: 1, + creativeId: 1, + dealId: 1, + currency: 'EUR', + netRevenue: true, + ttl: 600, + ad: '', + }; + + expect(result[0]).to.deep.equal(expectedResponse); + }); + + it('should return empty bid response because of timeout', function () { + let serverResponse = { + 'requestId': 'xyz654_2', + 'timeout': true, + 'ad': '', + }; + + let bidRequest = { + bidder: 'sublime', + adUnitCode: 'sublime_code_2', + bidId: 'abc1234_2', + data: { + w: 1, + h: 1, + }, + requestId: 'xyz654_2', + params: { + zoneId: 456, + } + }; + + let result = spec.interpretResponse({ body: serverResponse }, bidRequest); + + let expectedResponse = []; + + expect(result).to.deep.equal(expectedResponse); + }); + }); +}); From 3754a7110fc8f17f7e3a7ed9c92912bc9875010f Mon Sep 17 00:00:00 2001 From: mamatic <52153441+mamatic@users.noreply.github.com> Date: Mon, 19 Aug 2019 19:45:26 +0200 Subject: [PATCH 167/436] Identity Link - Use ats library for retrieving envelope (#4077) * Identity Link - Use ats library for retrieving envelope * Identity Link - add withCredentials options * Identity Link - renamed file identityLinkSystem to identityLinkIdSystem --- ...yLinkSystem.js => identityLinkIdSystem.js} | 42 +++++++++++++------ test/spec/modules/userId_spec.js | 2 +- 2 files changed, 30 insertions(+), 14 deletions(-) rename modules/{identityLinkSystem.js => identityLinkIdSystem.js} (60%) diff --git a/modules/identityLinkSystem.js b/modules/identityLinkIdSystem.js similarity index 60% rename from modules/identityLinkSystem.js rename to modules/identityLinkIdSystem.js index ef916252811..9aca5f85adf 100644 --- a/modules/identityLinkSystem.js +++ b/modules/identityLinkIdSystem.js @@ -38,21 +38,37 @@ export const identityLinkSubmodule = { } // use protocol relative urls for http or https const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}`; - - return function (callback) { - ajax(url, response => { - let responseObj; - if (response) { - try { - responseObj = JSON.parse(response); - } catch (error) { - utils.logError(error); + // if ats library is initialised, use it to retrieve envelope. If not use standard third party endpoint + if (window.ats) { + return function(callback) { + window.ats.retrieveEnvelope(function (envelope) { + if (envelope) { + callback(JSON.parse(envelope).envelope); + } else { + getEnvelope(url, callback); } - } - callback(responseObj.envelope); - }, undefined, { method: 'GET' }); + }); + } + } else { + return function (callback) { + getEnvelope(url, callback); + } } } -}; +} +// return envelope from third party endpoint +function getEnvelope(url, callback) { + ajax(url, response => { + let responseObj; + if (response) { + try { + responseObj = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + } + callback(responseObj.envelope); + }, undefined, {method: 'GET', withCredentials: true}); +} submodule('userId', identityLinkSubmodule); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index b581873089a..13f35b68545 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -10,7 +10,7 @@ import * as utils from 'src/utils'; import {unifiedIdSubmodule} from 'modules/userId/unifiedIdSystem'; import {pubCommonIdSubmodule} from 'modules/userId/pubCommonIdSystem'; import {id5IdSubmodule} from 'modules/id5IdSystem'; -import {identityLinkSubmodule} from 'modules/identityLinkSystem'; +import {identityLinkSubmodule} from 'modules/identityLinkIdSystem'; let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; From 1c604f565a0f0e12a00f45075c699130a75e1a9a Mon Sep 17 00:00:00 2001 From: Renato Aguilar <41385245+raguilar-ias@users.noreply.github.com> Date: Mon, 19 Aug 2019 18:43:17 -0500 Subject: [PATCH 168/436] OPT-1949 Update prebid.js to pass in window.href & add keyword process to our integration (#4083) * OPT-1949 Update prebid.js to pass in window.href & add keyword process to our integration * OPT-1949 remove kw custom value from test * OPT-1949 fix test * OPT-1949 specify url value --- modules/iasBidAdapter.js | 2 + test/spec/modules/iasBidAdapter_spec.js | 110 ++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/modules/iasBidAdapter.js b/modules/iasBidAdapter.js index bda5af1f4ec..5530cbefb82 100644 --- a/modules/iasBidAdapter.js +++ b/modules/iasBidAdapter.js @@ -59,6 +59,7 @@ function buildRequests(bidRequests) { queries.push(['wr', stringifyWindowSize()]); queries.push(['sr', stringifyScreenSize()]); + queries.push(['url', encodeURIComponent(window.location.href)]); const queryString = encodeURI(queries.map(qs => qs.join('=')).join('&')); @@ -80,6 +81,7 @@ function getPageLevelKeywords(response) { let result = {}; shallowMerge(result, response.brandSafety); result.fr = response.fr; + result.custom = response.custom; return result; } diff --git a/test/spec/modules/iasBidAdapter_spec.js b/test/spec/modules/iasBidAdapter_spec.js index 21ef9f8e15a..8197ee25856 100644 --- a/test/spec/modules/iasBidAdapter_spec.js +++ b/test/spec/modules/iasBidAdapter_spec.js @@ -116,6 +116,9 @@ describe('iasBidAdapter is an adapter that', function () { it('screen size', function () { expect(val).to.match(/.*sr=[0-9]*\.[0-9]*/); }); + it('url value', function () { + expect(val).to.match(/.*url=https?%3A%2F%2F[^\s$.?#].[^\s]*/); + }); }); it('has property `bidRequest` that is the first passed in bid request', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ @@ -229,5 +232,112 @@ describe('iasBidAdapter is an adapter that', function () { expect(adapter.interpretResponse(serverResponse, requests)).to.length(2); }); }); + describe('returns a list of bid response that with custom value', function () { + let bidRequests, bidResponse, slots, custom, serverResponse; + beforeEach(function () { + bidRequests = [ + { + adUnitCode: 'one-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId1', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/a/b/c' + }, + sizes: [ + [10, 20], + [300, 400] + ], + transactionId: 'someTransactionId' + }, + { + adUnitCode: 'two-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId2', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/d/e/f' + }, + sizes: [ + [50, 60] + ], + transactionId: 'someTransactionId' + } + ]; + const request = { + bidRequest: { + bidId: '102938' + } + }; + slots = {}; + slots['test-div-id'] = { + id: '1234', + vw: ['60', '70'] + }; + slots['test-div-id-two'] = { + id: '5678', + vw: ['80', '90'] + }; + custom = {}; + custom['ias-kw'] = ['IAS_1_KW', 'IAS_2_KW']; + serverResponse = { + body: { + brandSafety: { + adt: 'adtVal', + alc: 'alcVal', + dlm: 'dlmVal', + drg: 'drgVal', + hat: 'hatVal', + off: 'offVal', + vio: 'vioVal' + }, + fr: 'false', + slots: slots, + custom: custom + }, + headers: {} + }; + bidResponse = spec.interpretResponse(serverResponse, request); + }); + it('has IAS keyword `adt` as property', function () { + expect(bidResponse[0]).to.deep.include({ adt: 'adtVal' }); + }); + it('has IAS keyword `alc` as property', function () { + expect(bidResponse[0]).to.deep.include({ alc: 'alcVal' }); + }); + it('has IAS keyword `dlm` as property', function () { + expect(bidResponse[0]).to.deep.include({ dlm: 'dlmVal' }); + }); + it('has IAS keyword `drg` as property', function () { + expect(bidResponse[0]).to.deep.include({ drg: 'drgVal' }); + }); + it('has IAS keyword `hat` as property', function () { + expect(bidResponse[0]).to.deep.include({ hat: 'hatVal' }); + }); + it('has IAS keyword `off` as property', function () { + expect(bidResponse[0]).to.deep.include({ off: 'offVal' }); + }); + it('has IAS keyword `vio` as property', function () { + expect(bidResponse[0]).to.deep.include({ vio: 'vioVal' }); + }); + it('has IAS keyword `fr` as property', function () { + expect(bidResponse[0]).to.deep.include({ fr: 'false' }); + }); + it('has property `slots`', function () { + expect(bidResponse[0]).to.deep.include({ slots: slots }); + }); + it('has property `custom`', function () { + expect(bidResponse[0]).to.deep.include({ custom: custom }); + }); + it('response is the same for multiple slots', function () { + var adapter = spec; + var requests = adapter.buildRequests(bidRequests); + expect(adapter.interpretResponse(serverResponse, requests)).to.length(3); + }); + }); }); }); From 9248d7d1b7831e6bbb1e1d526fa261145755d70e Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 20 Aug 2019 08:19:45 -0400 Subject: [PATCH 169/436] Fix #4059 - ensure native keys are not seen as custom targeting keys (#4086) * ensure native keys are not seen as custom keys * add unit test for native keys --- src/targeting.js | 2 +- test/spec/unit/core/targeting_spec.js | 150 +++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index a8c989bdf37..f9ed9e4e70c 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -443,7 +443,7 @@ export function newTargeting(auctionManager) { } function getCustomKeys() { - let standardKeys = getStandardKeys(); + let standardKeys = getStandardKeys().concat(NATIVE_TARGETING_KEYS); return function(key) { return standardKeys.indexOf(key) === -1; } diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index bc5958f0495..f4d3a5e0488 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -97,6 +97,131 @@ const bid3 = { 'ttl': 300 }; +const nativeBid1 = { + 'bidderCode': 'appnexus', + 'width': 0, + 'height': 0, + 'statusMessage': 'Bid available', + 'adId': '591e7c9354b633', + 'requestId': '24aae81e32d6f6', + 'mediaType': 'native', + 'source': 'client', + 'cpm': 10, + 'creativeId': 97494403, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'adUnitCode': '/19968336/prebid_native_example_1', + 'appnexus': { + 'buyerMemberId': 9325 + }, + 'meta': { + 'advertiserId': 2529885 + }, + 'native': { + 'title': 'This is a Prebid Native Creative', + 'body': 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + 'sponsoredBy': 'Prebid.org', + 'clickUrl': 'http://prebid.org/dev-docs/show-native-ads.html', + 'clickTrackers': ['http://www.clickUrl.com/404'], + 'impressionTrackers': ['http://imp.trackerUrl.com/it1'], + 'javascriptTrackers': '', + 'image': { + 'url': 'http://vcdn.adnxs.com/p/creative-image/94/22/cd/0f/9422cd0f-f400-45d3-80f5-2b92629d9257.jpg', + 'height': 2250, + 'width': 3000 + }, + 'icon': { + 'url': 'http://vcdn.adnxs.com/p/creative-image/bd/59/a6/c6/bd59a6c6-0851-411d-a16d-031475a51312.png', + 'height': 83, + 'width': 127 + } + }, + 'auctionId': '72138a4a-b747-4192-9192-dcc41d675de8', + 'responseTimestamp': 1565785219461, + 'requestTimestamp': 1565785219405, + 'bidder': 'appnexus', + 'timeToRespond': 56, + 'pbLg': '5.00', + 'pbMg': '10.00', + 'pbHg': '10.00', + 'pbAg': '10.00', + 'pbDg': '10.00', + 'pbCg': '', + 'size': '0x0', + 'adserverTargeting': { + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'appnexus', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '591e7c9354b633', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '10.00', + [CONSTANTS.TARGETING_KEYS.SIZE]: '0x0', + [CONSTANTS.TARGETING_KEYS.SOURCE]: 'client', + [CONSTANTS.TARGETING_KEYS.FORMAT]: 'native', + [CONSTANTS.NATIVE_KEYS.title]: 'This is a Prebid Native Creative', + [CONSTANTS.NATIVE_KEYS.body]: 'This is a Prebid Native Creative. There are many like it, but this one is mine.', + [CONSTANTS.NATIVE_KEYS.sponsoredBy]: 'Prebid.org', + [CONSTANTS.NATIVE_KEYS.clickUrl]: 'http://prebid.org/dev-docs/show-native-ads.html', + [CONSTANTS.NATIVE_KEYS.image]: 'http://vcdn.adnxs.com/p/creative-image/94/22/cd/0f/9422cd0f-f400-45d3-80f5-2b92629d9257.jpg', + [CONSTANTS.NATIVE_KEYS.icon]: 'http://vcdn.adnxs.com/p/creative-image/bd/59/a6/c6/bd59a6c6-0851-411d-a16d-031475a51312.png' + } +}; +const nativeBid2 = { + 'bidderCode': 'dgads', + 'width': 0, + 'height': 0, + 'statusMessage': 'Bid available', + 'adId': '6e0aba55ed54e5', + 'requestId': '4de26ec83d9661', + 'mediaType': 'native', + 'source': 'client', + 'cpm': 1.90909091, + 'creativeId': 'xuidx6c901261b0x2b2', + 'currency': 'JPY', + 'netRevenue': true, + 'ttl': 60, + 'referrer': 'http://test.localhost:9999/integrationExamples/gpt/demo_native.html?pbjs_debug=true', + 'native': { + 'image': { + 'url': 'https://ads-tr.bigmining.com/img/300x250.png', + 'width': 300, + 'height': 250 + }, + 'title': 'Test Title', + 'body': 'Test Description', + 'sponsoredBy': 'test.com', + 'clickUrl': 'http://prebid.org/', + 'clickTrackers': ['https://www.clickUrl.com/404'], + 'impressionTrackers': [ + 'http://imp.trackerUrl.com/it2' + ] + }, + 'auctionId': '72138a4a-b747-4192-9192-dcc41d675de8', + 'responseTimestamp': 1565785219607, + 'requestTimestamp': 1565785219409, + 'bidder': 'dgads', + 'adUnitCode': '/19968336/prebid_native_example_1', + 'timeToRespond': 198, + 'pbLg': '1.50', + 'pbMg': '1.90', + 'pbHg': '1.90', + 'pbAg': '1.90', + 'pbDg': '1.90', + 'pbCg': '', + 'size': '0x0', + 'adserverTargeting': { + [CONSTANTS.TARGETING_KEYS.BIDDER]: 'dgads', + [CONSTANTS.TARGETING_KEYS.AD_ID]: '6e0aba55ed54e5', + [CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]: '1.90', + [CONSTANTS.TARGETING_KEYS.SIZE]: '0x0', + [CONSTANTS.TARGETING_KEYS.SOURCE]: 'client', + [CONSTANTS.TARGETING_KEYS.FORMAT]: 'native', + [CONSTANTS.NATIVE_KEYS.image]: 'https://ads-tr.bigmining.com/img/300x250.png', + [CONSTANTS.NATIVE_KEYS.title]: 'Test Title', + [CONSTANTS.NATIVE_KEYS.body]: 'Test Description', + [CONSTANTS.NATIVE_KEYS.sponsoredBy]: 'test.com', + [CONSTANTS.NATIVE_KEYS.clickUrl]: 'http://prebid.org/' + } +}; + describe('targeting tests', function () { let sandbox; let enableSendAllBids = false; @@ -106,7 +231,6 @@ describe('targeting tests', function () { sandbox = sinon.sandbox.create(); useBidCache = true; - // enableSendAllBids = false; let origGetConfig = config.getConfig; sandbox.stub(config, 'getConfig').callsFake(function (key) { @@ -150,6 +274,9 @@ describe('targeting tests', function () { config.resetConfig(); logWarnStub.restore(); logErrorStub.restore(); + amBidsReceivedStub.restore(); + amGetAdUnitsStub.restore(); + bidExpiryStub.restore(); }); describe('when hb_deal is present in bid.adserverTargeting', function () { @@ -218,6 +345,27 @@ describe('targeting tests', function () { expect(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET + '_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0'][CONSTANTS.TARGETING_KEYS.PRICE_BUCKET]); }); + it('ensures keys are properly generated when enableSendAllBids is true and multiple bidders use native', function() { + const nativeAdUnitCode = '/19968336/prebid_native_example_1'; + enableSendAllBids = true; + + // update mocks for this test to return native bids + amBidsReceivedStub.callsFake(function() { + return [nativeBid1, nativeBid2]; + }); + amGetAdUnitsStub.callsFake(function() { + return [nativeAdUnitCode]; + }); + + let targeting = targetingInstance.getAllTargeting([nativeAdUnitCode]); + expect(targeting[nativeAdUnitCode].hb_native_image).to.equal(nativeBid1.native.image.url); + expect(targeting[nativeAdUnitCode].hb_native_linkurl).to.equal(nativeBid1.native.clickUrl); + expect(targeting[nativeAdUnitCode].hb_native_title).to.equal(nativeBid1.native.title); + expect(targeting[nativeAdUnitCode].hb_native_image_dgad).to.exist.and.to.equal(nativeBid2.native.image.url); + expect(targeting[nativeAdUnitCode].hb_pb_dgads).to.exist.and.to.equal(nativeBid2.pbMg); + expect(targeting[nativeAdUnitCode].hb_native_body_appne).to.exist.and.to.equal(nativeBid1.native.body); + }); + it('does not include adpod type bids in the getBidsReceived results', function () { let adpodBid = utils.deepClone(bid1); adpodBid.video = { context: 'adpod', durationSeconds: 15, durationBucket: 15 }; From 7d8a9c7da0fae33c697442844b915e33903f0dbd Mon Sep 17 00:00:00 2001 From: Cosmos Dev <48195282+dev-cosmos@users.noreply.github.com> Date: Tue, 20 Aug 2019 19:58:56 +0530 Subject: [PATCH 170/436] New Adapter request : cosmos (#4096) * Create cosmosBidAdapter.js Implemented cosmos adapter * Create cosmosBidAdapter.md Document file for cosmos * Create cosmos_sample.html Test File * Deleted cosmos_sample.html * Added unittesting. --- modules/cosmosBidAdapter.js | 392 +++++++++++++++++++++ modules/cosmosBidAdapter.md | 80 +++++ test/spec/modules/cosmosBidAdapter_spec.js | 355 +++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 modules/cosmosBidAdapter.js create mode 100644 modules/cosmosBidAdapter.md create mode 100644 test/spec/modules/cosmosBidAdapter_spec.js diff --git a/modules/cosmosBidAdapter.js b/modules/cosmosBidAdapter.js new file mode 100644 index 00000000000..84131bfa131 --- /dev/null +++ b/modules/cosmosBidAdapter.js @@ -0,0 +1,392 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import * as utils from '../src/utils'; + +const BIDDER_CODE = 'cosmos'; +const BID_ENDPOINT = '//bid.cosmoshq.com/openrtb2/bids'; +const USER_SYNC_ENDPOINT = '//sync.cosmoshq.com/js/v1/usersync.html'; +const HTTP_POST = 'POST'; +const LOG_PREFIX = 'COSMOS: '; +const DEFAULT_CURRENCY = 'USD'; +const HTTPS = 'https:'; +const MEDIA_TYPES = 'mediaTypes'; +const MIMES = 'mimes'; +const DEFAULT_NET_REVENUE = false; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + + /** + * generate UUID + **/ + _createUUID: function () { + return ('' + new Date().getTime()); + }, + + /** + * copy object if not null + **/ + _copyObject: function (src, dst) { + if (src) { + // copy complete object + Object.keys(src).forEach(param => dst[param] = src[param]); + } + }, + + /** + * parse object + **/ + _parse: function (rawPayload) { + try { + if (rawPayload) { + return JSON.parse(rawPayload); + } + } catch (ex) { + utils.logError(LOG_PREFIX, 'Exception: ', ex); + } + return null; + }, + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + **/ + isBidRequestValid: function (bid) { + if (!bid || !bid.params) { + utils.logError(LOG_PREFIX, 'nil/empty bid object'); + return false; + } + + if (!utils.isEmpty(bid.params.publisherId) || + !utils.isNumber(bid.params.publisherId)) { + utils.logError(LOG_PREFIX, 'publisherId is mandatory and must be numeric. Ad Unit: ', JSON.stringify(bid)); + return false; + } + // video bid request validation + if (bid.hasOwnProperty(MEDIA_TYPES) && bid.mediaTypes.hasOwnProperty(VIDEO)) { + if (!bid.mediaTypes.video.hasOwnProperty(MIMES) || + !utils.isArray(bid.mediaTypes.video.mimes) || + bid.mediaTypes.video.mimes.length === 0) { + utils.logError(LOG_PREFIX, 'mimes are mandatory for video bid request. Ad Unit: ', JSON.stringify(bid)); + return false; + } + } + + return true; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + **/ + buildRequests: function (validBidRequests, bidderRequest) { + if (validBidRequests.length === 0) { + return []; + } + + var refererInfo; + if (bidderRequest && bidderRequest.refererInfo) { + refererInfo = bidderRequest.refererInfo; + } + + let clonedBidRequests = utils.deepClone(validBidRequests); + return clonedBidRequests.map(bidRequest => { + const oRequest = spec._createRequest(bidRequest, refererInfo); + if (oRequest) { + spec._setGDPRParams(bidderRequest, oRequest); + return { + method: HTTP_POST, + url: BID_ENDPOINT, + data: JSON.stringify(oRequest) + }; + } + }); + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + **/ + interpretResponse: function (serverResponse, request) { + let response = serverResponse.body; + var bidResponses = []; + try { + if (response.seatbid) { + var currency = response.cur ? response.cur : DEFAULT_CURRENCY; + response.seatbid.forEach(seatbid => { + var bids = seatbid.bid ? seatbid.bid : []; + bids.forEach(bid => { + var bidResponse = { + requestId: bid.impid, + cpm: (parseFloat(bid.price) || 0).toFixed(2), + width: bid.w, + height: bid.h, + creativeId: bid.crid, + currency: currency, + netRevenue: DEFAULT_NET_REVENUE, + ttl: 300 + }; + if (bid.dealid) { + bidResponse.dealId = bid.dealid; + } + + var req = spec._parse(request.data); + if (req.imp && req.imp.length > 0) { + req.imp.forEach(impr => { + if (impr.id === bid.impid) { + if (impr.banner) { + bidResponse.ad = bid.adm; + bidResponse.mediaType = BANNER; + } else { + bidResponse.width = bid.hasOwnProperty('w') ? bid.w : impr.video.w; + bidResponse.height = bid.hasOwnProperty('h') ? bid.h : impr.video.h; + bidResponse.vastXml = bid.adm; + bidResponse.mediaType = VIDEO; + } + } + }); + } + bidResponses.push(bidResponse); + }); + }); + } + } catch (ex) { + utils.logError(LOG_PREFIX, 'Exception: ', ex); + } + return bidResponses; + }, + + /** + * Register the user sync pixels which should be dropped after the auction. + * @param {SyncOptions} syncOptions Which user syncs are allowed? + * @param {ServerResponse[]} serverResponses List of server's responses. + * @return {UserSync[]} The user syncs which should be dropped. + **/ + getUserSyncs: function (syncOptions, serverResponses) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USER_SYNC_ENDPOINT + }]; + } else { + utils.logWarn(LOG_PREFIX + 'Please enable iframe based user sync.'); + } + }, + + /** + * create IAB standard OpenRTB bid request + **/ + _createRequest: function (bidRequests, refererInfo) { + var oRequest = {}; + try { + oRequest = { + id: spec._createUUID(), + imp: spec._createImpressions(bidRequests), + user: {}, + ext: {} + }; + var site = spec._createSite(bidRequests, refererInfo); + var app = spec._createApp(bidRequests); + var device = spec._createDevice(bidRequests); + if (app) { + oRequest.app = app; + } + if (site) { + oRequest.site = site; + } + if (device) { + oRequest.device = device; + } + } catch (ex) { + utils.logError(LOG_PREFIX, 'Exception: ', ex); + oRequest = null; + } + return oRequest; + }, + + /** + * create impression array objects + **/ + _createImpressions: function (request) { + var impressions = []; + var impression = spec._creatImpression(request); + if (impression) { + impressions.push(impression); + } + return impressions; + }, + + /** + * create impression (single) object + **/ + _creatImpression: function (request) { + if (!request.hasOwnProperty(MEDIA_TYPES)) { + return undefined; + } + + var params = request && request.params ? request.params : null; + var impression = { + id: request.bidId ? request.bidId : spec._createUUID(), + secure: window.location.protocol === HTTPS ? 1 : 0, + bidfloorcur: request.params.currency ? request.params.currency : DEFAULT_CURRENCY + }; + if (params.bidFloor) { + impression.bidfloor = params.bidFloor; + } + + if (params.tagId) { + impression.tagid = params.tagId.toString(); + } + + var banner; + var video; + var mediaType; + for (mediaType in request.mediaTypes) { + switch (mediaType) { + case BANNER: + banner = spec._createBanner(request); + if (banner) { + impression.banner = banner; + } + break; + case VIDEO: + video = spec._createVideo(request); + if (video) { + impression.video = video; + } + break; + } + } + + return impression.hasOwnProperty(BANNER) || + impression.hasOwnProperty(VIDEO) ? impression : undefined; + }, + + /** + * create the banner object + **/ + _createBanner: function (request) { + if (utils.deepAccess(request, 'mediaTypes.banner')) { + var banner = {}; + var sizes = request.mediaTypes.banner.sizes; + if (sizes && utils.isArray(sizes) && sizes.length > 0) { + var format = []; + banner.w = sizes[0][0]; + banner.h = sizes[0][1]; + sizes.forEach(size => { + format.push({ + w: size[0], + h: size[1] + }); + }); + banner.format = format; + } + + spec._copyObject(request.mediaTypes.banner, banner); + spec._copyObject(request.params.banner, banner); + return banner; + } + return undefined; + }, + + /** + * create video object + **/ + _createVideo: function (request) { + if (utils.deepAccess(request, 'mediaTypes.video')) { + var video = {}; + var sizes = request.mediaTypes.video.playerSize; + if (sizes && utils.isArray(sizes) && sizes.length > 1) { + video.w = sizes[0]; + video.h = sizes[1]; + } + spec._copyObject(request.mediaTypes.video, video); + spec._copyObject(request.params.video, video); + return video; + } + return undefined; + }, + + /** + * create site object + **/ + _createSite: function (request, refererInfo) { + var rSite = request.params.site; + if (rSite || !request.params.app) { + var site = {}; + spec._copyObject(rSite, site); + + if (refererInfo) { + if (refererInfo.referer) { + site.ref = encodeURIComponent(refererInfo.referer); + } + if (utils.isArray(refererInfo.stack) && refererInfo.stack.length > 0) { + site.page = encodeURIComponent(refererInfo.stack[0]); + let anchrTag = document.createElement('a'); + anchrTag.href = site.page; + site.domain = anchrTag.hostname; + } + } + + // override publisher object + site.publisher = { + id: request.params.publisherId.toString() + }; + return site; + } + return undefined; + }, + + /** + * create app object + **/ + _createApp: function (request) { + var rApp = request.params.app; + if (rApp) { + var app = {}; + spec._copyObject(rApp, app); + // override publisher object + app.publisher = { + id: request.params.publisherId.toString() + }; + return app; + } + return undefined; + }, + + /** + * create device obejct + **/ + _createDevice: function (request) { + var device = {}; + var rDevice = request.params.device; + spec._copyObject(rDevice, device); + device.dnt = utils.getDNT() ? 1 : 0; + device.ua = navigator.userAgent; + device.language = (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage); + device.w = (window.screen.width || window.innerWidth); + device.h = (window.screen.height || window.innerHeigh); + return device; + }, + + /** + * set GDPR parameters + **/ + _setGDPRParams: function (bidderRequest, oRequest) { + if (!bidderRequest || !bidderRequest.gdprConsent) { + return; + } + + oRequest.regs = { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0 } }; + oRequest.user = { ext: { consent: bidderRequest.gdprConsent.consentString } }; + }, + +} +registerBidder(spec); diff --git a/modules/cosmosBidAdapter.md b/modules/cosmosBidAdapter.md new file mode 100644 index 00000000000..187a19ba17a --- /dev/null +++ b/modules/cosmosBidAdapter.md @@ -0,0 +1,80 @@ +# Overview + +``` +Module Name: Cosmos Bid Adapter +Module Type: Bidder Adapter +Maintainer: dev@cosmoshq.com +``` + +# Description + +Module that connects to Cosmos server for bids. +Supported Ad Fortmats: +* Banner +* Video + +# Configuration +## Following configuration required for enabling user sync. +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['cosmos'], + syncDelay: 6000 + }}); +``` +## For Video ads, enable prebid cache +```javascript +pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } +}); +``` + +# Test Parameters +``` + var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { //supported as per the openRTB spec + sizes: [[300, 250]] // required + } + }, + bids: [ + { + bidder: "cosmos", + params: { + publisherId: 1001, // required + tagId: 1 // optional + } + } + ] + }, + // Video adUnit + { + code: 'video-div', + mediaTypes: { + video: { // supported as per the openRTB spec + sizes: [[300, 50]], // required + mimes : ['video/mp4', 'application/javascript'], // required + context: 'instream' // optional + } + }, + bids: [ + { + bidder: "cosmos", + params: { + publisherId: 1001, // required + tagId: 1, // optional + video: { // supported as per the openRTB spec + + } + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/cosmosBidAdapter_spec.js b/test/spec/modules/cosmosBidAdapter_spec.js new file mode 100644 index 00000000000..348f5ae3ddf --- /dev/null +++ b/test/spec/modules/cosmosBidAdapter_spec.js @@ -0,0 +1,355 @@ +import { expect } from 'chai'; +import { spec } from 'modules/cosmosBidAdapter'; +import * as utils from 'src/utils'; +const constants = require('src/constants.json'); + +describe('Cosmos adapter', function () { + let bannerBidRequests; + let bannerBidResponse; + let videoBidRequests; + let videoBidResponse; + + beforeEach(function () { + bannerBidRequests = [ + { + bidder: 'cosmos', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + params: { + publisherId: '1001', + currency: 'USD', + geo: { + lat: '09.5', + lon: '21.2', + } + }, + bidId: '29f8bd96defe76' + } + ]; + + videoBidRequests = + [ + { + mediaTypes: { + video: { + mimes: ['video/mp4', 'video/x-flv'], + context: 'instream' + } + }, + bidder: 'cosmos', + params: { + publisherId: 1001, + video: { + skippable: true, + minduration: 5, + maxduration: 30 + } + }, + bidId: '39f5cc6eff9b37' + } + ]; + + bannerBidResponse = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '82DAAE22-FF66-4FAB-84AB-347B0C5CD02C', + 'impid': '29f8bd96defe76', + 'price': 1.858309, + 'adm': '

COSMOS\"Connecting Advertisers and Publishers directly\"

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

Prebid.js Banner Ad Unit Test

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

Prebid Video -- video.js

- \ No newline at end of file + diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 09ca6217fe2..58b90b0a017 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -31,7 +31,8 @@ describe('OneVideoBidAdapter', function () { delivery: [2], playbackmethod: [1, 5], placement: 123, - sid: 134 + sid: 134, + rewarded: 1 }, site: { id: 1, @@ -67,7 +68,8 @@ describe('OneVideoBidAdapter', function () { delivery: [2], playbackmethod: [1, 5], placement: 123, - sid: 134 + sid: 134, + rewarded: 1 } }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); @@ -84,7 +86,8 @@ describe('OneVideoBidAdapter', function () { delivery: [2], playbackmethod: [1, 5], placement: 123, - sid: 134 + sid: 134, + rewarded: 1 }, pubId: 'brxd' }; @@ -114,10 +117,12 @@ describe('OneVideoBidAdapter', function () { const data = requests[0].data; const [ width, height ] = bidRequest.sizes; const placement = bidRequest.params.video.placement; + const rewarded = bidRequest.params.video.rewarded; expect(data.imp[0].video.w).to.equal(width); expect(data.imp[0].video.h).to.equal(height); expect(data.imp[0].ext.placement).to.equal(placement); expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); + expect(data.imp[0].ext.rewarded).to.equal(rewarded); }); it('must parse bid size from a nested array', function () { From 0308c525e0acc85e4c1595abb31a6badb07e3e26 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 9 Sep 2019 10:56:51 -0700 Subject: [PATCH 215/436] Module to pass User Ids to DFP (#4140) * first commit * renamed * minor doc change * documentation * small change * EB * removed unused imports * minor changes * reanmaed a const * adding more methods to test shareUserIds module * unit tets cases for shareUserIds * indentation * renamed DFP to GAM * renamed shareUserIds to userIdTargeting * Update userIdTargeting.md * trying to restart CI * digitrust userId case handled * minor comment change * using auctionEnd event instead of requestBids.before * using events.on --- modules/userIdTargeting.js | 61 ++++++++++++++++++++++++++ modules/userIdTargeting.md | 37 ++++++++++++++++ test/spec/modules/shareUserIds_spec.js | 53 ++++++++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 13 ++++++ 4 files changed, 164 insertions(+) create mode 100644 modules/userIdTargeting.js create mode 100644 modules/userIdTargeting.md create mode 100644 test/spec/modules/shareUserIds_spec.js diff --git a/modules/userIdTargeting.js b/modules/userIdTargeting.js new file mode 100644 index 00000000000..2a19bd62fbb --- /dev/null +++ b/modules/userIdTargeting.js @@ -0,0 +1,61 @@ +import {config} from '../src/config'; +import {getGlobal} from '../src/prebidGlobal'; +import CONSTANTS from '../src/constants.json'; +import events from '../src/events'; +import { isStr, isPlainObject, isBoolean, isFn, hasOwn, logInfo } from '../src/utils'; + +const MODULE_NAME = 'userIdTargeting'; +const GAM = 'GAM'; +const GAM_KEYS_CONFIG = 'GAM_KEYS'; + +export function userIdTargeting(userIds, config) { + if (!isPlainObject(config)) { + logInfo(MODULE_NAME + ': Invalid config found, not sharing userIds externally.'); + return; + } + + const PUB_GAM_KEYS = isPlainObject(config[GAM_KEYS_CONFIG]) ? config[GAM_KEYS_CONFIG] : {}; + let SHARE_WITH_GAM = isBoolean(config[GAM]) ? config[GAM] : false; + let GAM_API; + + if (!SHARE_WITH_GAM) { + logInfo(MODULE_NAME + ': Not enabled for ' + GAM); + } + + if (window.googletag && isFn(window.googletag.pubads) && hasOwn(window.googletag.pubads(), 'setTargeting') && isFn(window.googletag.pubads().setTargeting)) { + GAM_API = window.googletag.pubads().setTargeting; + } else { + SHARE_WITH_GAM = false; + logInfo(MODULE_NAME + ': Could not find googletag.pubads().setTargeting API. Not adding User Ids in targeting.') + return; + } + + Object.keys(userIds).forEach(function(key) { + if (userIds[key]) { + // PUB_GAM_KEYS: { "tdid": '' } means the publisher does not want to send the tdid to GAM + if (SHARE_WITH_GAM && PUB_GAM_KEYS[key] !== '') { + let uidStr; + if (isStr(userIds[key])) { + uidStr = userIds[key]; + } else if (isPlainObject(userIds[key])) { + uidStr = JSON.stringify(userIds[key]) + } else { + logInfo(MODULE_NAME + ': ' + key + ' User ID is not an object or a string.'); + return; + } + GAM_API( + (hasOwn(PUB_GAM_KEYS, key) ? PUB_GAM_KEYS[key] : key), + [ uidStr ] + ); + } + } + }); +} + +export function init(config) { + events.on(CONSTANTS.EVENTS.AUCTION_END, function() { + userIdTargeting((getGlobal()).getUserIds(), config.getConfig(MODULE_NAME)); + }) +} + +init(config) diff --git a/modules/userIdTargeting.md b/modules/userIdTargeting.md new file mode 100644 index 00000000000..f99fd5308b3 --- /dev/null +++ b/modules/userIdTargeting.md @@ -0,0 +1,37 @@ +## userIdTargeting Module +- This module works with userId module. +- This module is used to pass userIds to GAM in targeting so that user ids can be used to pass in Google Exchange Bidding or can be used for targeting in GAM. + +## Sample config +``` +pbjs.setConfig({ + + // your existing userIds config + + usersync: { + userIds: [{...}, ...] + }, + + // new userIdTargeting config + + userIdTargeting: { + "GAM": true, + "GAM_KEYS": { + "tdid": "TTD_ID" // send tdid as TTD_ID + } + } +}); +``` + +## Config options +- GAM: is required to be set to true if a publisher wants to send UserIds as targeting in GAM call. This module uses ``` googletag.pubads().setTargeting('key-name', ['value']) ``` API to set GAM targeting. +- GAM_KEYS: is an optional config object to be used with ``` "GAM": true ```. If not passed then all UserIds are passed with respective key-name used in UserIds object. +If a publisher wants to pass ```UserId.tdid``` as TTD_ID in targeting then set ``` GAM_KEYS: { "tdid": "TTD_ID" }``` +If a publisher does not wants to pass ```UserId.tdid``` but wants to pass other Ids in UserId tthen set ``` GAM_KEYS: { "tdid": "" }``` + +## Including this module in Prebid +``` $ gulp build --modules=userId,userIdTargeting,pubmaticBidAdapter ``` + +## Notes +- We can add support for other external systems like GAM in future +- We have not added support for A9/APSTag as it is called in parallel with Prebid. This module executes when ```pbjs.requestBids``` is called, in practice, call to A9 is expected to execute in paralle to Prebid thus we have not covered A9 here. For sending Uids in A9, one will need to set those Ids in params key in the object passed to ```apstag.init```, ```pbjs.getUserIds``` can be used for the same. diff --git a/test/spec/modules/shareUserIds_spec.js b/test/spec/modules/shareUserIds_spec.js new file mode 100644 index 00000000000..4ae5f93a1a6 --- /dev/null +++ b/test/spec/modules/shareUserIds_spec.js @@ -0,0 +1,53 @@ +import {userIdTargeting} from '../../../modules/userIdTargeting'; +import { expect } from 'chai'; + +describe('#userIdTargeting', function() { + let userIds; + let config; + + beforeEach(function() { + userIds = { + tdid: 'my-tdid' + }; + config = { + 'GAM': true, + 'GAM_KEYS': { + 'tdid': 'TD_ID' + } + }; + }); + + it('Do nothing if config is invaild', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + userIdTargeting(userIds, JSON.stringify(config)); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST']}); + }); + + it('all UserIds are passed as is with GAM: true', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + delete config.GAM_KEYS; + userIdTargeting(userIds, config); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST'], tdid: ['my-tdid']}); + }) + + it('Publisher prefered key-names are used', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + userIdTargeting(userIds, config); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST'], 'TD_ID': ['my-tdid']}); + }); + + it('Publisher does not want to pass an id', function() { + let pubads = window.googletag.pubads(); + pubads.clearTargeting(); + pubads.setTargeting('test', ['TEST']); + config.GAM_KEYS.tdid = ''; + userIdTargeting(userIds, config); + expect(pubads.getTargeting()).to.deep.equal({test: ['TEST']}); + }); +}); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index c73604cac82..485dd5cf077 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -108,6 +108,7 @@ var createSlotArrayScenario2 = function createSlotArrayScenario2() { window.googletag = { _slots: [], + _targeting: {}, pubads: function () { var self = this; return { @@ -117,6 +118,18 @@ window.googletag = { setSlots: function (slots) { self._slots = slots; + }, + + setTargeting: function(key, arrayOfValues) { + self._targeting[key] = arrayOfValues; + }, + + getTargeting: function() { + return self._targeting; + }, + + clearTargeting: function() { + self._targeting = {}; } }; } From b0124f2876e693dc4e43ec91207648f1fb97caed Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 10 Sep 2019 07:13:28 +0300 Subject: [PATCH 216/436] Buzzoola bid adapter (#4127) * initial commit for buzzoola adapter * leave only banners for now * fix bid validation * change endpoint url * add video type * restore renderer * fix renderer * add fixed player sizes * switch bids * convert dimentions to strings * write tests * 100% tests * remove new DOM element creation in tests * handle empty response from server * change description --- modules/buzzoolaBidAdapter.js | 108 + modules/buzzoolaBidAdapter.md | 72 + package-lock.json | 6864 +++++++++++++++--- test/spec/modules/buzzoolaBidAdapter_spec.js | 279 + 4 files changed, 6388 insertions(+), 935 deletions(-) create mode 100644 modules/buzzoolaBidAdapter.js create mode 100644 modules/buzzoolaBidAdapter.md create mode 100644 test/spec/modules/buzzoolaBidAdapter_spec.js diff --git a/modules/buzzoolaBidAdapter.js b/modules/buzzoolaBidAdapter.js new file mode 100644 index 00000000000..da2a3b30c2e --- /dev/null +++ b/modules/buzzoolaBidAdapter.js @@ -0,0 +1,108 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, VIDEO} from '../src/mediaTypes'; +import {Renderer} from '../src/Renderer'; +import {OUTSTREAM} from '../src/video'; + +const BIDDER_CODE = 'buzzoola'; +const ENDPOINT = 'https://exchange.buzzoola.com/ssp/prebidjs'; +const RENDERER_SRC = 'https://tube.buzzoola.com/new/build/buzzlibrary.js'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['buzzoolaAdapter'], + supportedMediaTypes: [BANNER, VIDEO], + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return {boolean} True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bid) { + let types = bid.mediaTypes; + return !!(bid && bid.mediaTypes && (types.banner || types.video) && bid.params && bid.params.placementId); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests an array of bids + * @param bidderRequest + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + return { + url: ENDPOINT, + method: 'POST', + data: bidderRequest, + } + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param bidderRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function ({body}, {data}) { + let requestBids = {}; + let response; + + try { + response = JSON.parse(body); + } catch (ex) { + response = body; + } + + if (!Array.isArray(response)) response = []; + + data.bids.forEach(bid => requestBids[bid.bidId] = bid); + + return response.map(bid => { + let requestBid = requestBids[bid.requestId]; + let context = utils.deepAccess(requestBid, 'mediaTypes.video.context'); + let validBid = utils.deepClone(bid); + + if (validBid.mediaType === VIDEO && context === OUTSTREAM) { + let renderer = Renderer.install({ + id: validBid.requestId, + url: RENDERER_SRC, + loaded: false + }); + + renderer.setRender(setOutstreamRenderer); + validBid.renderer = renderer + } + + return validBid; + }); + } +}; + +/** + * Initialize Buzzoola Outstream player + * + * @param bid + */ +function setOutstreamRenderer(bid) { + let adData = JSON.parse(bid.ad); + let unitSettings = utils.deepAccess(adData, 'placement.unit_settings'); + let extendedSettings = { + width: '' + bid.width, + height: '' + bid.height, + container_height: '' + bid.height + }; + + adData.placement = Object.assign({}, adData.placement); + adData.placement.unit_settings = Object.assign({}, unitSettings, extendedSettings); + + bid.renderer.push(() => { + window.Buzzoola.Core.install(document.querySelector(`#${bid.adUnitCode}`), { + data: adData + }); + }); +} + +registerBidder(spec); diff --git a/modules/buzzoolaBidAdapter.md b/modules/buzzoolaBidAdapter.md new file mode 100644 index 00000000000..aec3eda6c58 --- /dev/null +++ b/modules/buzzoolaBidAdapter.md @@ -0,0 +1,72 @@ +# Overview + +``` +Module Name: Buzzoola Bid Adapter +Module Type: Bidder Adapter +Maintainer: devteam@buzzoola.com +``` + +# Description + +Connects to Buzzoola exchange for bids. + +Buzzoola bid adapter supports Banner and Video (instream and outstream). + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[240, 400], [300, 600]], + } + }, + bids: [{ + bidder: 'buzzoola', + params: { + placementId: 417846 + } + }] + }, + // Video instream adUnit + { + code: 'video-instream', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 380], + mimes: ['video/mp4'], + minduration: 1, + maxduration: 2, + } + }, + bids: [{ + bidder: 'buzzoola', + params: { + placementId: 417845 + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 380], + mimes: ['video/mp4'], + minduration: 1, + maxduration: 2, + } + }, + bids: [{ + bidder: 'buzzoola', + params: { + placementId: 417845 + } + }] + } +]; +``` diff --git a/package-lock.json b/package-lock.json index e8e1461cbe8..9013350fb01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,97 +1,173 @@ { "name": "prebid.js", - "version": "2.27.0-pre", + "version": "2.30.0-pre", "lockfileVersion": 1, + "requires": true, "dependencies": { "@babel/code-frame": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } }, "@babel/core": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", - "dev": true + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } }, "@babel/generator": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } }, "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-call-delegate": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } }, "@babel/helper-define-map": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } }, "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-hoist-variables": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } }, "@babel/helper-member-expression-to-functions": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.5.5" + } }, "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-module-transforms": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } }, "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, "@babel/helper-plugin-utils": { "version": "7.0.0", @@ -103,49 +179,88 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.13" + } }, "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-replace-supers": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } }, "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } }, "@babel/helper-split-export-declaration": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } }, "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } }, "@babel/helpers": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", - "dev": true + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } }, "@babel/highlight": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "dev": true + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } }, "@babel/parser": { "version": "7.5.5", @@ -157,289 +272,535 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } }, "@babel/plugin-proposal-dynamic-import": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } }, "@babel/plugin-proposal-object-rest-spread": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } }, "@babel/plugin-syntax-async-generators": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-dynamic-import": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-syntax-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-async-to-generator": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } }, "@babel/plugin-transform-block-scoped-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-block-scoping": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.13" + } }, "@babel/plugin-transform-classes": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" + } }, "@babel/plugin-transform-computed-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-destructuring": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-dotall-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } }, "@babel/plugin-transform-duplicate-keys": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-for-of": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-function-name": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-member-expression-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-modules-amd": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, "@babel/plugin-transform-modules-commonjs": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, "@babel/plugin-transform-modules-systemjs": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, "@babel/plugin-transform-modules-umd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==", - "dev": true + "dev": true, + "requires": { + "regexp-tree": "^0.1.6" + } }, "@babel/plugin-transform-new-target": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-object-super": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5" + } }, "@babel/plugin-transform-parameters": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-property-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-regenerator": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } }, "@babel/plugin-transform-reserved-words": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-spread": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-sticky-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } }, "@babel/plugin-transform-template-literals": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-typeof-symbol": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + } }, "@babel/preset-env": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", - "dev": true + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.5.5", + "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.5.0", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-duplicate-keys": "^7.5.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-modules-systemjs": "^7.5.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", + "@babel/plugin-transform-object-super": "^7.5.5", + "@babel/plugin-transform-parameters": "^7.4.4", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-reserved-words": "^7.2.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.5.5", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + } }, "@babel/template": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } }, "@babel/traverse": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", - "dev": true + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } }, "@babel/types": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } }, "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, "source-map": { "version": "0.6.1", @@ -454,12 +815,19 @@ "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -469,23 +837,14 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true }, - "@sinonjs/commons": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", - "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", - "dev": true - }, "@sinonjs/formatio": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "dev": true - }, - "@sinonjs/samsam": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", - "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", - "dev": true + "dev": true, + "requires": { + "samsam": "1.3.0" + } }, "@sinonjs/text-encoding": { "version": "0.7.1", @@ -493,6 +852,16 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -503,7 +872,11 @@ "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } }, "acorn": { "version": "5.7.3", @@ -516,6 +889,9 @@ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", "dev": true, + "requires": { + "acorn": "^4.0.3" + }, "dependencies": { "acorn": { "version": "4.0.13", @@ -530,6 +906,9 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, + "requires": { + "acorn": "^3.0.4" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -555,13 +934,22 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } }, "ajv-keywords": { "version": "2.1.1", @@ -574,12 +962,20 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -605,7 +1001,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-html": { "version": "0.0.7", @@ -616,14 +1015,16 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "ansi-wrap": { "version": "0.1.0", @@ -636,12 +1037,19 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -649,25 +1057,44 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } }, "append-transform": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + }, "dependencies": { "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -676,12 +1103,23 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", "dev": true, + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -695,7 +1133,10 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } }, "arr-diff": { "version": "4.0.0", @@ -707,7 +1148,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-flatten": { "version": "1.1.0", @@ -719,7 +1163,10 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } }, "arr-union": { "version": "3.1.0", @@ -757,23 +1204,25 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, "array-includes": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -788,6 +1237,9 @@ "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, + "requires": { + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -820,6 +1272,11 @@ "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -851,25 +1308,36 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, "dependencies": { "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, "util": { "version": "0.10.3", @@ -907,7 +1375,13 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } }, "async-each": { "version": "1.0.3", @@ -925,7 +1399,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true + "dev": true, + "requires": { + "async-done": "^1.2.2" + } }, "asynckit": { "version": "0.4.0", @@ -956,6 +1433,11 @@ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -967,7 +1449,14 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } }, "js-tokens": { "version": "3.0.2", @@ -988,12 +1477,36 @@ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "json5": { "version": "0.5.1", @@ -1014,6 +1527,16 @@ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, "dependencies": { "jsesc": { "version": "1.3.0", @@ -1027,115 +1550,211 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-builder-react-jsx": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } }, "babel-helper-call-delegate": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-define-map": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-get-function-arity": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-helper-regex": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-helper-remap-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-loader": { "version": "8.0.6", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "dev": true + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" + } }, "babel-messages": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-dynamic-import-node": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", @@ -1225,181 +1844,323 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-system-import-transformer/-/babel-plugin-system-import-transformer-3.1.0.tgz", "integrity": "sha1-038Mro5h7zkGAggzHZMbXmMNfF8=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0" + } }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-class-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-decorators": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true + "dev": true, + "requires": { + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-decorators-legacy": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "^6.1.18", + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" + } }, "babel-plugin-transform-do-expressions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } }, "babel-plugin-transform-es2015-classes": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-for-of": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-plugin-transform-es2015-object-super": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-parameters": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-spread": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -1411,7 +2172,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } }, "regjsgen": { "version": "0.2.0", @@ -1423,7 +2189,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } } } }, @@ -1431,72 +2200,120 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-function-bind": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-object-assign": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=" + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-self": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-react-jsx-source": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } }, "babel-plugin-transform-regenerator": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + }, "dependencies": { "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } } } }, @@ -1504,19 +2321,59 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } }, "babel-preset-env": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + }, "dependencies": { "browserslist": { "version": "3.2.8", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } } } }, @@ -1524,66 +2381,134 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } }, "babel-preset-stage-0": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "^6.22.0", + "babel-plugin-transform-function-bind": "^6.22.0", + "babel-preset-stage-1": "^6.24.1" + } }, "babel-preset-stage-1": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "^6.24.1", + "babel-plugin-transform-export-extensions": "^6.22.0", + "babel-preset-stage-2": "^6.24.1" + } }, "babel-preset-stage-2": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" + } }, "babel-preset-stage-3": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.22.0" + } }, "babel-register": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=" + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } }, "babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } }, "babel-traverse": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "globals": { "version": "9.18.0", @@ -1604,6 +2529,12 @@ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, "dependencies": { "to-fast-properties": { "version": "1.0.3", @@ -1629,7 +2560,18 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } }, "backo2": { "version": "1.0.2", @@ -1654,30 +2596,53 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -1709,7 +2674,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } }, "beeper": { "version": "1.1.1", @@ -1721,13 +2689,22 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true + "dev": true, + "requires": { + "callsite": "1.0.0" + } }, "bfj": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", - "dev": true + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } }, "big.js": { "version": "5.2.2", @@ -1751,7 +2728,11 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } }, "blob": { "version": "0.0.5", @@ -1775,13 +2756,31 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true + "dev": true, + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, "dependencies": { "bytes": { "version": "3.1.0", @@ -1799,7 +2798,14 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, "inherits": { "version": "2.0.3", @@ -1810,8 +2816,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "qs": { "version": "6.7.0", @@ -1823,7 +2828,13 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } }, "setprototypeof": { "version": "1.1.1", @@ -1837,19 +2848,38 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -1864,6 +2894,9 @@ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, + "requires": { + "resolve": "1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -1883,67 +2916,124 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } }, "browserify-des": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } }, "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true + "dev": true, + "requires": { + "pako": "~1.0.5" + } }, "browserslist": { "version": "4.6.6", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", - "dev": true + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000984", + "electron-to-chromium": "^1.3.191", + "node-releases": "^1.1.25" + } }, "browserstack": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", - "dev": true + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } }, "browserstack-local": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.2.tgz", "integrity": "sha512-fRaynjF0MvtyyfPRy2NFnVwxLyNtD28K/v9xRsIjUVf7xLc80NIm7Nfr3KXlFmWizhG91PL/UAOXlHkoxQjaNw==", - "dev": true + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1", + "is-running": "^2.0.0", + "ps-tree": "=1.1.1", + "temp-fs": "^0.9.9" + } }, "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } }, "buffer-alloc-unsafe": { "version": "1.1.0", @@ -2003,13 +3093,33 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, "dependencies": { "lowercase-keys": { "version": "1.0.0", @@ -2021,7 +3131,12 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } }, "prepend-http": { "version": "2.0.0", @@ -2033,13 +3148,21 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } } } }, @@ -2047,7 +3170,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true + "dev": true, + "requires": { + "callsites": "^0.2.0" + } }, "callsite": { "version": "1.0.0", @@ -2072,6 +3198,10 @@ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, "dependencies": { "camelcase": { "version": "2.1.1", @@ -2103,19 +3233,36 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "character-entities": { "version": "1.2.3", @@ -2163,13 +3310,31 @@ "version": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", - "dev": true + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "circular-json": { "version": "0.3.3", @@ -2182,12 +3347,21 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -2195,7 +3369,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } }, "cli-width": { "version": "2.2.0", @@ -2208,6 +3385,11 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -2219,7 +3401,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -2239,7 +3424,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "clone-stats": { "version": "1.0.0", @@ -2251,7 +3439,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } }, "co": { "version": "4.6.0", @@ -2262,8 +3455,7 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "collapse-white-space": { "version": "1.0.5", @@ -2275,19 +3467,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true + "dev": true, + "requires": { + "color-name": "1.1.3" + } }, "color-name": { "version": "1.1.3", @@ -2311,13 +3515,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.5.0" + } }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } }, "comma-separated-tokens": { "version": "1.0.7", @@ -2360,12 +3570,21 @@ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", "dev": true, + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -2379,13 +3598,22 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "concat-with-sourcemaps": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, + "requires": { + "source-map": "^0.6.1" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -2400,6 +3628,12 @@ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -2410,8 +3644,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2425,7 +3658,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true + "dev": true, + "requires": { + "date-now": "^0.1.4" + } }, "constants-browserify": { "version": "1.0.0", @@ -2443,7 +3679,10 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } }, "content-type": { "version": "1.0.4", @@ -2461,7 +3700,10 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, "cookie": { "version": "0.3.1", @@ -2485,7 +3727,11 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } }, "core-js": { "version": "2.6.9", @@ -2497,6 +3743,11 @@ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", "integrity": "sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg==", "dev": true, + "requires": { + "browserslist": "^4.6.2", + "core-js-pure": "3.1.4", + "semver": "^6.1.1" + }, "dependencies": { "semver": { "version": "6.3.0", @@ -2522,49 +3773,103 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.5.tgz", "integrity": "sha512-/KD7PGfZv/tjKB6LoW97jzIgFqem0Tu9tZL9/iwBnBd8zkIZp7vT1ZSHNvnr0GSQMV/LTMxUstWg8WcDDUVQKg==", - "dev": true + "dev": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.13.1", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.86.0" + } }, "crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true + "dev": true, + "requires": { + "buffer": "^5.1.0" + } }, "crc32-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true + "dev": true, + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } }, "create-hmac": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } }, "crypto-js": { "version": "3.1.9-1", @@ -2576,6 +3881,12 @@ "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -2589,7 +3900,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true + "dev": true, + "requires": { + "css": "^2.0.0" + } }, "css-value": { "version": "0.0.1", @@ -2601,7 +3915,10 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } }, "custom-event": { "version": "1.0.1", @@ -2613,13 +3930,20 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } }, "date-format": { "version": "1.2.0", @@ -2637,25 +3961,40 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "debug-fabulous": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -2675,13 +4014,19 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } }, "deep-is": { "version": "0.1.3", @@ -2700,6 +4045,9 @@ "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -2714,12 +4062,18 @@ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, + "requires": { + "strip-bom": "^2.0.0" + }, "dependencies": { "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -2733,31 +4087,49 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -2783,7 +4155,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "destroy": { "version": "1.0.4", @@ -2795,7 +4171,10 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.2.tgz", "integrity": "sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ==", - "dev": true + "dev": true, + "requires": { + "repeat-string": "^1.5.4" + } }, "detect-file": { "version": "1.0.0", @@ -2807,7 +4186,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "detect-libc": { "version": "1.0.3", @@ -2825,7 +4207,11 @@ "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } }, "di": { "version": "0.0.1", @@ -2843,13 +4229,22 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } }, "disparity": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", "dev": true, + "requires": { + "ansi-styles": "^2.0.1", + "diff": "^1.3.2" + }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -2868,19 +4263,78 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "doctrine-temporary-fork": { "version": "2.0.0-alpha-allowarrayindex", "resolved": "https://registry.npmjs.org/doctrine-temporary-fork/-/doctrine-temporary-fork-2.0.0-alpha-allowarrayindex.tgz", "integrity": "sha1-QAFahn6yfnWybIKLcVJPE3+J+fA=", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } }, "documentation": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/documentation/-/documentation-5.5.0.tgz", "integrity": "sha512-Aod3HOI+8zMhwWztDlECRsDfJ8SFu4oADvipOLq3gnWKy4Cpg2oF5AWT+U6PcX85KuguDI6c+q+2YwYEx99B/A==", "dev": true, + "requires": { + "ansi-html": "^0.0.7", + "babel-core": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-plugin-system-import-transformer": "3.1.0", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-preset-env": "^1.6.1", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-0": "^6.24.1", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babelify": "^8.0.0", + "babylon": "^6.18.0", + "chalk": "^2.3.0", + "chokidar": "^2.0.0", + "concat-stream": "^1.6.0", + "disparity": "^2.0.0", + "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", + "get-port": "^3.2.0", + "git-url-parse": "^8.0.0", + "github-slugger": "1.2.0", + "glob": "^7.1.2", + "globals-docs": "^2.4.0", + "highlight.js": "^9.12.0", + "js-yaml": "^3.10.0", + "lodash": "^4.17.4", + "mdast-util-inject": "^1.1.0", + "micromatch": "^3.1.5", + "mime": "^1.4.1", + "module-deps-sortable": "4.0.6", + "parse-filepath": "^1.0.2", + "pify": "^3.0.0", + "read-pkg-up": "^3.0.0", + "remark": "^9.0.0", + "remark-html": "7.0.0", + "remark-reference-links": "^4.0.1", + "remark-toc": "^5.0.0", + "remote-origin-url": "0.4.0", + "shelljs": "^0.8.1", + "stream-array": "^1.1.2", + "strip-json-comments": "^2.0.1", + "tiny-lr": "^1.1.0", + "unist-builder": "^1.0.2", + "unist-util-visit": "^1.3.0", + "vfile": "^2.3.0", + "vfile-reporter": "^4.0.0", + "vfile-sort": "^2.1.0", + "vinyl": "^2.1.0", + "vinyl-fs": "^3.0.2", + "yargs": "^9.0.1" + }, "dependencies": { "camelcase": { "version": "4.1.0", @@ -2893,12 +4347,22 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, "dependencies": { "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -2906,19 +4370,36 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "get-caller-file": { "version": "1.0.3", @@ -2936,19 +4417,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -2962,19 +4455,30 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -2986,19 +4490,30 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "dev": true, + "requires": { + "p-try": "^1.0.0" + } }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-try": { "version": "1.0.0", @@ -3010,13 +4525,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, + "requires": { + "pify": "^2.0.0" + }, "dependencies": { "pify": { "version": "2.3.0", @@ -3036,7 +4557,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } }, "require-main-filename": { "version": "1.0.1", @@ -3061,12 +4587,31 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, "dependencies": { "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } } } }, @@ -3074,7 +4619,10 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -3082,7 +4630,13 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } }, "domain-browser": { "version": "1.2.0", @@ -3105,7 +4659,10 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "duplexer3": { "version": "0.1.4", @@ -3117,19 +4674,33 @@ "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } }, "each-props": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } }, "editions": { "version": "1.3.4", @@ -3159,7 +4730,16 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } }, "emoji-regex": { "version": "7.0.3", @@ -3183,19 +4763,33 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true + "dev": true, + "requires": { + "once": "^1.4.0" + } }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3210,6 +4804,19 @@ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -3221,7 +4828,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3235,13 +4845,26 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" + } }, "ent": { "version": "2.2.0", @@ -3253,37 +4876,65 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true + "dev": true, + "requires": { + "prr": "~1.0.1" + } }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true + "dev": true, + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } }, "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } }, "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", - "dev": true + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "^1.0.0" + } }, "es5-shim": { "version": "4.5.13", @@ -3295,13 +4946,26 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } }, "es6-map": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-promise": { "version": "4.2.8", @@ -3313,25 +4977,45 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "es6-weak-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } }, "escape-html": { "version": "1.0.3", @@ -3350,6 +5034,13 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, "dependencies": { "esprima": { "version": "2.7.3", @@ -3368,7 +5059,10 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, - "optional": true + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -3376,13 +5070,59 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -3394,31 +5134,49 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2" + } }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, "yallist": { "version": "2.1.2", @@ -3439,12 +5197,19 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -3459,6 +5224,10 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -3469,38 +5238,32 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "pkg-dir": { "version": "2.0.0", @@ -3515,6 +5278,19 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", "dev": true, + "requires": { + "array-includes": "^3.0.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -3525,68 +5301,57 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=" }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=" }, "read-pkg-up": { "version": "2.0.0", @@ -3601,6 +5366,12 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", @@ -3630,7 +5401,11 @@ "version": "3.7.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint-visitor-keys": { "version": "1.0.0", @@ -3642,7 +5417,11 @@ "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } }, "esprima": { "version": "4.0.1", @@ -3654,13 +5433,19 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } }, "estraverse": { "version": "4.2.0", @@ -3684,13 +5469,26 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + }, "dependencies": { "map-stream": { "version": "0.1.0", @@ -3716,19 +5514,35 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, "dependencies": { "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true + "dev": true, + "requires": { + "pump": "^3.0.0" + } } } }, @@ -3737,6 +5551,11 @@ "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, "dependencies": { "array-slice": { "version": "0.2.3", @@ -3754,7 +5573,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } } } }, @@ -3763,24 +5585,42 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "ms": { "version": "2.0.0", @@ -3795,6 +5635,10 @@ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + }, "dependencies": { "is-number": { "version": "0.1.1", @@ -3814,13 +5658,48 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, "dependencies": { "cookie": { "version": "0.4.0", @@ -3832,13 +5711,23 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "http-errors": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, "ms": { "version": "2.0.0", @@ -3863,6 +5752,21 @@ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, "dependencies": { "ms": { "version": "2.1.1", @@ -3891,12 +5795,19 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -3904,43 +5815,75 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -3960,7 +5903,13 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } }, "fast-deep-equal": { "version": "1.1.0", @@ -3984,25 +5933,38 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } }, "fibers": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", "integrity": "sha512-dl3Ukt08rHVQfY8xGD0ODwyjwrRALtaghuqGH2jByYX1wpY+nAnRQjJ6Dbqq0DnVgNVQ9yibObzbF4IlPyiwPw==", - "dev": true + "dev": true, + "requires": { + "detect-libc": "^1.0.3" + } }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } }, "file-entry-cache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } }, "filename-regex": { "version": "2.0.1", @@ -4014,7 +5976,11 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } }, "filesize": { "version": "3.6.1", @@ -4027,12 +5993,21 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -4041,6 +6016,15 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, "dependencies": { "debug": { "version": "2.6.9", @@ -4051,8 +6035,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -4060,25 +6043,46 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } }, "findup-sync": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } }, "fined": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } }, "flagged-respawn": { "version": "1.0.1", @@ -4091,6 +6095,9 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, "dependencies": { "is-buffer": { "version": "2.0.3", @@ -4105,12 +6112,21 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + }, "dependencies": { "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -4124,19 +6140,29 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } }, "follow-redirects": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, + "requires": { + "debug": "^3.2.6" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -4150,7 +6176,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true + "dev": true, + "requires": { + "for-in": "^1.0.1" + } }, "foreachasync": { "version": "3.0.0", @@ -4174,7 +6203,12 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } }, "forwarded": { "version": "0.1.2", @@ -4186,7 +6220,10 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } }, "fresh": { "version": "0.5.2", @@ -4204,13 +6241,20 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } }, "fs-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true + "dev": true, + "requires": { + "null-check": "^1.0.0" + } }, "fs-constants": { "version": "1.0.0", @@ -4223,6 +6267,12 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.6.4.tgz", "integrity": "sha1-9G8MdbeEH40gCzNIzU1pHVoJnRU=", "dev": true, + "requires": { + "jsonfile": "~1.0.1", + "mkdirp": "0.3.x", + "ncp": "~0.4.2", + "rimraf": "~2.2.0" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -4236,13 +6286,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } }, "fs.extra": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fs.extra/-/fs.extra-1.3.2.tgz", "integrity": "sha1-3QI/kwE77iRTHxszUUw3sg/ZM0k=", "dev": true, + "requires": { + "fs-extra": "~0.6.1", + "mkdirp": "~0.3.5", + "walk": "^2.3.9" + }, "dependencies": { "mkdirp": { "version": "0.3.5", @@ -4264,6 +6323,10 @@ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, "dependencies": { "abbrev": { "version": "1.1.1", @@ -4274,7 +6337,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4286,17 +6350,27 @@ "version": "1.1.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } }, "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "chownr": { "version": "1.1.1", @@ -4307,17 +6381,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4329,7 +6406,10 @@ "version": "4.1.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ms": "^2.1.1" + } }, "deep-extend": { "version": "0.6.0", @@ -4353,7 +6433,10 @@ "version": "1.2.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "fs.realpath": { "version": "1.0.0", @@ -4365,13 +6448,31 @@ "version": "2.7.4", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } }, "glob": { "version": "7.1.3", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-unicode": { "version": "2.0.1", @@ -4383,24 +6484,35 @@ "version": "0.4.24", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4411,7 +6523,11 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "isarray": { "version": "1.0.0", @@ -4422,28 +6538,45 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } }, "minizlib": { "version": "1.2.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "minipass": "^2.2.1" + } }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "2.1.1", @@ -4455,19 +6588,40 @@ "version": "2.3.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } }, "node-pre-gyp": { "version": "0.12.0", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } }, "npm-bundled": { "version": "1.0.6", @@ -4479,18 +6633,29 @@ "version": "1.4.1", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } }, "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4501,7 +6666,11 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } }, "os-homedir": { "version": "1.0.2", @@ -4519,7 +6688,11 @@ "version": "0.1.5", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "path-is-absolute": { "version": "1.0.1", @@ -4538,6 +6711,12 @@ "bundled": true, "dev": true, "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -4551,18 +6730,31 @@ "version": "2.3.6", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, "rimraf": { "version": "2.6.3", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "glob": "^7.1.3" + } }, "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4594,21 +6786,34 @@ "dev": true, "optional": true }, - "string_decoder": { - "version": "1.1.1", + "string-width": { + "version": "1.0.2", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, - "string-width": { - "version": "1.0.2", + "string_decoder": { + "version": "1.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-json-comments": { "version": "2.0.1", @@ -4620,7 +6825,16 @@ "version": "4.4.8", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } }, "util-deprecate": { "version": "1.0.2", @@ -4632,17 +6846,22 @@ "version": "1.1.3", "bundled": true, "dev": true, - "optional": true + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -4667,7 +6886,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true + "dev": true, + "requires": { + "globule": "^1.0.0" + } }, "get-caller-file": { "version": "2.0.5", @@ -4709,25 +6931,39 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } }, "git-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.1.0.tgz", "integrity": "sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA==", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^3.0.2" + } }, "git-url-parse": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-8.3.1.tgz", "integrity": "sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ==", - "dev": true + "dev": true, + "requires": { + "git-up": "^2.0.0", + "parse-domain": "^2.0.0" + } }, "github-slugger": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.0.tgz", "integrity": "sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q==", "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -4741,19 +6977,34 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, "dependencies": { "glob-parent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "is-extglob": { "version": "1.0.0", @@ -4765,7 +7016,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -4774,12 +7028,19 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -4787,25 +7048,57 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } }, "glob-watcher": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", - "dev": true + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } }, "global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } }, "globals": { "version": "11.12.0", @@ -4823,19 +7116,46 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", "dev": true, + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, "dependencies": { "pify": { "version": "3.0.0", @@ -4868,138 +7188,163 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, "dependencies": { "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" }, "gulp-cli": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", - "dev": true + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + } }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "requires": { + "number-is-nan": "^1.0.0" + } }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "requires": { + "invert-kv": "^1.0.0" + } }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=" }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" }, "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "y18n": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yargs": { "version": "7.1.0", @@ -5010,8 +7355,7 @@ "yargs-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=" } } }, @@ -5020,6 +7364,11 @@ "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", "dev": true, + "requires": { + "gulp-util": "^2.2.14", + "rimraf": "^2.2.8", + "through2": "^0.4.2" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -5037,7 +7386,14 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^1.1.0", + "escape-string-regexp": "^1.0.0", + "has-ansi": "^0.1.0", + "strip-ansi": "^0.3.0", + "supports-color": "^0.2.0" + } }, "clone-stats": { "version": "0.0.1", @@ -5050,12 +7406,26 @@ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", "dev": true, + "requires": { + "chalk": "^0.5.0", + "dateformat": "^1.0.7-1.2.3", + "lodash._reinterpolate": "^2.4.1", + "lodash.template": "^2.4.1", + "minimist": "^0.2.0", + "multipipe": "^0.1.0", + "through2": "^0.5.0", + "vinyl": "^0.2.1" + }, "dependencies": { "through2": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } } } }, @@ -5063,7 +7433,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.0" + } }, "isarray": { "version": "0.0.1", @@ -5087,7 +7460,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -5099,7 +7478,10 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } }, "supports-color": { "version": "0.2.0", @@ -5112,12 +7494,19 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~2.1.1" + }, "dependencies": { "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true + "dev": true, + "requires": { + "object-keys": "~0.4.0" + } } } }, @@ -5125,7 +7514,10 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true + "dev": true, + "requires": { + "clone-stats": "~0.0.1" + } }, "xtend": { "version": "3.0.0", @@ -5139,13 +7531,29 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } }, "gulp-connect": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz", "integrity": "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==", "dev": true, + "requires": { + "ansi-colors": "^2.0.5", + "connect": "^3.6.6", + "connect-livereload": "^0.6.0", + "fancy-log": "^1.3.2", + "map-stream": "^0.0.7", + "send": "^0.16.2", + "serve-index": "^1.9.1", + "serve-static": "^1.13.2", + "tiny-lr": "^1.1.1" + }, "dependencies": { "ansi-colors": { "version": "2.0.5", @@ -5159,11 +7567,24 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.2.tgz", "integrity": "sha512-fcFUQzFsN6dJ6KZlG+qPOEkqfcevRUXgztkYCvhNvJeSvOicC8ucutN4qR/ID8LmNZx9YPIkBzazTNnVvbh8wg==", - "dev": true + "dev": true, + "requires": { + "eslint": "^4.0.0", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.0" + } }, "gulp-footer": { "version": "github:prebid/gulp-footer#ff2b46e6376c7f04900357ff9f7b30f219fe5f8a", + "from": "github:prebid/gulp-footer#master", "dev": true, + "requires": { + "event-stream": "3.3.4", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.6.2" + }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -5175,25 +7596,48 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } }, "lodash.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } } } }, @@ -5202,6 +7646,11 @@ "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", "dev": true, + "requires": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + }, "dependencies": { "lodash._reinterpolate": { "version": "3.0.0", @@ -5213,13 +7662,20 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } }, "lodash.templatesettings": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } } } }, @@ -5227,13 +7683,21 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true + "dev": true, + "requires": { + "gulp-match": "^1.0.3", + "ternary-stream": "^2.0.1", + "through2": "^2.0.1" + } }, "gulp-js-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gulp-js-escape/-/gulp-js-escape-1.0.1.tgz", "integrity": "sha1-HNRF+9AJ4Np2lZoDp/SbNWav+Gg=", "dev": true, + "requires": { + "through2": "^0.6.3" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -5245,7 +7709,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -5257,7 +7727,11 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } } } }, @@ -5265,25 +7739,52 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", - "dev": true + "dev": true, + "requires": { + "minimatch": "^3.0.3" + } }, "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", - "dev": true + "dev": true, + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + } }, "gulp-shell": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/gulp-shell/-/gulp-shell-0.5.2.tgz", "integrity": "sha1-pJWcoGUa0ce7/nCy0K27tOGuqY0=", - "dev": true + "dev": true, + "requires": { + "async": "^1.5.0", + "gulp-util": "^3.0.7", + "lodash": "^4.0.0", + "through2": "^2.0.0" + } }, "gulp-sourcemaps": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.5.tgz", "integrity": "sha512-SYLBRzPTew8T5Suh2U8jCSDKY+4NARua4aqjj8HOysBh2tSgT9u4jc1FYirAdPx1akUxxDeK++fqw6Jg0LkQRg==", "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -5297,13 +7798,45 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, "dependencies": { "ansi-styles": { "version": "2.2.1", @@ -5315,7 +7848,14 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } }, "clone": { "version": "1.0.4", @@ -5345,25 +7885,48 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } }, "lodash.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } }, "object-assign": { "version": "3.0.0", @@ -5387,7 +7950,12 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } } } }, @@ -5395,19 +7963,32 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true + "dev": true, + "requires": { + "glogg": "^1.0.0" + } }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", - "dev": true + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + } }, "handlebars": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -5428,12 +8009,22 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, "dependencies": { "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } }, "fast-deep-equal": { "version": "2.0.1", @@ -5453,19 +8044,28 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, + "requires": { + "isarray": "2.0.1" + }, "dependencies": { "isarray": { "version": "2.0.1", @@ -5491,7 +8091,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "has-symbol-support-x": { "version": "1.4.2", @@ -5509,25 +8112,40 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } }, "has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5535,13 +8153,21 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } }, "hast-util-is-element": { "version": "1.0.3", @@ -5553,13 +8179,29 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-1.3.1.tgz", "integrity": "sha512-AIeKHuHx0Wk45nSkGVa2/ujQYTksnDl8gmmKo/mwQi7ag7IBZ8cM3nJ2G86SajbjGP/HRpud6kMkPtcM2i0Tlw==", - "dev": true + "dev": true, + "requires": { + "xtend": "^4.0.1" + } }, "hast-util-to-html": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-3.1.0.tgz", "integrity": "sha1-iCyZhJ5AEw6ZHAQuRW1FPZXDbP8=", "dev": true, + "requires": { + "ccount": "^1.0.0", + "comma-separated-tokens": "^1.0.1", + "hast-util-is-element": "^1.0.0", + "hast-util-whitespace": "^1.0.0", + "html-void-elements": "^1.0.0", + "kebab-case": "^1.0.0", + "property-information": "^3.1.0", + "space-separated-tokens": "^1.0.0", + "stringify-entities": "^1.0.1", + "unist-util-is": "^2.0.0", + "xtend": "^4.0.1" + }, "dependencies": { "unist-util-is": { "version": "2.1.3", @@ -5591,19 +8233,31 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } }, "hoopy": { "version": "0.1.4", @@ -5615,7 +8269,10 @@ "version": "2.8.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.2.tgz", "integrity": "sha512-CyjlXII6LMsPMyUzxpTt8fzh5QwzGqPmQXgY/Jyf4Zfp27t/FvfhwoE/8laaMUcMy816CkWF20I7NeQhwwY88w==", - "dev": true + "dev": true, + "requires": { + "lru-cache": "^5.1.1" + } }, "html-void-elements": { "version": "1.0.4", @@ -5634,6 +8291,12 @@ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, "dependencies": { "inherits": { "version": "2.0.3", @@ -5653,13 +8316,23 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "https-browserify": { "version": "1.0.0", @@ -5672,6 +8345,10 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, "dependencies": { "debug": { "version": "3.2.6", @@ -5691,7 +8368,10 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ieee754": { "version": "1.1.13", @@ -5715,7 +8395,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "indexof": { "version": "0.0.1", @@ -5727,7 +8410,11 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.4", @@ -5746,6 +8433,22 @@ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -5757,7 +8460,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -5771,13 +8477,20 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true + "dev": true, + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } }, "invert-kv": { "version": "2.0.0", @@ -5795,19 +8508,29 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5827,7 +8550,11 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -5839,7 +8566,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } }, "is-buffer": { "version": "1.1.6", @@ -5858,12 +8588,18 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5884,6 +8620,11 @@ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -5909,7 +8650,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } }, "is-extendable": { "version": "0.1.1", @@ -5927,7 +8671,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -5939,7 +8686,10 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } }, "is-hexadecimal": { "version": "1.0.3", @@ -5958,12 +8708,18 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5983,7 +8739,10 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "is-posix-bracket": { "version": "0.1.1", @@ -6007,13 +8766,19 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true + "dev": true, + "requires": { + "has": "^1.0.1" + } }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } }, "is-resolvable": { "version": "1.1.0", @@ -6037,7 +8802,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", - "dev": true + "dev": true, + "requires": { + "protocols": "^1.1.0" + } }, "is-stream": { "version": "1.1.0", @@ -6049,7 +8817,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } }, "is-typedarray": { "version": "1.0.0", @@ -6061,7 +8832,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } }, "is-utf8": { "version": "0.2.1", @@ -6109,7 +8883,10 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -6134,6 +8911,22 @@ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, "dependencies": { "esprima": { "version": "2.7.3", @@ -6145,7 +8938,14 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -6163,7 +8963,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -6172,12 +8975,28 @@ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + }, "dependencies": { "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -6185,7 +9004,13 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + } }, "istanbul-lib-coverage": { "version": "1.2.1", @@ -6197,19 +9022,37 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } }, "istanbul-lib-instrument": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } }, "istanbul-lib-report": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, "dependencies": { "has-flag": { "version": "1.0.0", @@ -6221,7 +9064,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } } } }, @@ -6230,18 +9076,31 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -6249,19 +9108,31 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } }, "istextorbinary": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } }, "js-levenshtein": { "version": "1.1.6", @@ -6279,7 +9150,11 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "jsbn": { "version": "0.1.1", @@ -6344,7 +9219,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true + "dev": true, + "requires": { + "minimist": "^1.2.0" + } }, "jsonfile": { "version": "1.0.1", @@ -6358,23 +9236,23 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } }, "just-clone": { "version": "1.0.2", @@ -6398,6 +9276,36 @@ "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.5", + "log4js": "^3.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, "dependencies": { "mime": { "version": "2.4.4", @@ -6409,7 +9317,10 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.1.3" + } }, "source-map": { "version": "0.6.1", @@ -6423,13 +9334,21 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/karma-babel-preprocessor/-/karma-babel-preprocessor-6.0.1.tgz", "integrity": "sha1-euHT5klQ2+EfQht0BAqwj7WmbCE=", - "dev": true + "dev": true, + "requires": { + "babel-core": "^6.0.0" + } }, "karma-browserstack-launcher": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.5.1.tgz", "integrity": "sha512-zt9Ukow5A9WZHZXCFVO/h5kRsAdaZYeMNJK9Uan8v42amQXt3B/DZVxl24NCcAIxufKjW13UWd9iJ9knG9OCYw==", - "dev": true + "dev": true, + "requires": { + "browserstack": "~1.5.1", + "browserstack-local": "^1.3.7", + "q": "~1.5.0" + } }, "karma-chai": { "version": "0.1.0", @@ -6441,19 +9360,30 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } }, "karma-coverage-istanbul-reporter": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", - "dev": true + "dev": true, + "requires": { + "istanbul-api": "^1.3.1", + "minimatch": "^3.0.4" + } }, "karma-es5-shim": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/karma-es5-shim/-/karma-es5-shim-0.0.4.tgz", "integrity": "sha1-zdADM8znfC5M4D46yT8vjs0fuVI=", - "dev": true + "dev": true, + "requires": { + "es5-shim": "^4.0.5" + } }, "karma-firefox-launcher": { "version": "1.1.0", @@ -6465,19 +9395,30 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz", "integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.6.1" + } }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true + "dev": true, + "requires": { + "minimist": "1.2.0" + } }, "karma-mocha-reporter": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "strip-ansi": "^4.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -6489,7 +9430,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -6521,25 +9465,42 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + } }, "karma-spec-reporter": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz", "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", - "dev": true + "dev": true, + "requires": { + "colors": "^1.1.2" + } }, "karma-webpack": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", "dev": true, + "requires": { + "async": "^2.0.0", + "babel-runtime": "^6.0.0", + "loader-utils": "^1.0.0", + "lodash": "^4.0.0", + "source-map": "^0.5.6", + "webpack-dev-middleware": "^2.0.6" + }, "dependencies": { "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -6553,7 +9514,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } }, "kind-of": { "version": "6.0.2", @@ -6565,7 +9529,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } }, "lazy-cache": { "version": "1.0.4", @@ -6577,13 +9545,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } }, "lcov-parse": { "version": "0.0.10", @@ -6595,19 +9569,36 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } }, "livereload-js": { "version": "2.4.0", @@ -6620,6 +9611,12 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, "dependencies": { "pify": { "version": "3.0.0", @@ -6640,12 +9637,20 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + }, "dependencies": { "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true + "dev": true, + "requires": { + "minimist": "^1.2.0" + } } } }, @@ -6653,7 +9658,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } }, "lodash": { "version": "4.17.15", @@ -6683,7 +9692,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1" + } }, "lodash._escapestringchar": { "version": "2.4.1", @@ -6743,7 +9755,11 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash._root": { "version": "3.0.1", @@ -6755,7 +9771,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "lodash.clone": { "version": "4.5.0", @@ -6767,13 +9786,22 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash.escape": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true + "dev": true, + "requires": { + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" + } }, "lodash.get": { "version": "4.4.2", @@ -6797,13 +9825,21 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } }, "lodash.keys": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } }, "lodash.restparam": { "version": "3.6.1", @@ -6821,19 +9857,35 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true + "dev": true, + "requires": { + "lodash._escapestringchar": "~2.4.1", + "lodash._reinterpolate": "~2.4.1", + "lodash.defaults": "~2.4.1", + "lodash.escape": "~2.4.1", + "lodash.keys": "~2.4.1", + "lodash.templatesettings": "~2.4.1", + "lodash.values": "~2.4.1" + } }, "lodash.templatesettings": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" + } }, "lodash.values": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", - "dev": true + "dev": true, + "requires": { + "lodash.keys": "~2.4.1" + } }, "log-driver": { "version": "1.2.7", @@ -6845,13 +9897,23 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true + "dev": true, + "requires": { + "chalk": "^2.0.1" + } }, "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, + "requires": { + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" + }, "dependencies": { "circular-json": { "version": "0.5.9", @@ -6863,7 +9925,10 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -6871,7 +9936,11 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "dev": true + "dev": true, + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } }, "lolex": { "version": "2.7.5", @@ -6895,13 +9964,20 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } }, "lowercase-keys": { "version": "1.0.1", @@ -6913,19 +9989,29 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true + "dev": true, + "requires": { + "yallist": "^3.0.2" + } }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } }, "make-error": { "version": "1.3.5", @@ -6937,19 +10023,28 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true + "dev": true, + "requires": { + "make-error": "^1.2.0" + } }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } }, "map-cache": { "version": "0.2.2", @@ -6973,7 +10068,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } }, "markdown-escapes": { "version": "1.0.3", @@ -6992,18 +10090,33 @@ "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, "dependencies": { "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } } } }, @@ -7017,31 +10130,58 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "mdast-util-compact": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz", "integrity": "sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "mdast-util-definitions": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-1.2.4.tgz", "integrity": "sha512-HfUArPog1j4Z78Xlzy9Q4aHLnrF/7fb57cooTHypyGoe2XFNbcx/kWZDoOz+ra8CkUzvg3+VHV434yqEd1DRmA==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "mdast-util-inject": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mdast-util-inject/-/mdast-util-inject-1.1.0.tgz", "integrity": "sha1-2wa4tYW+lZotzS+H9HK6m3VvNnU=", - "dev": true + "dev": true, + "requires": { + "mdast-util-to-string": "^1.0.0" + } }, "mdast-util-to-hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-3.0.4.tgz", "integrity": "sha512-/eIbly2YmyVgpJNo+bFLLMCI1XgolO/Ffowhf+pHDq3X4/V6FntC9sGQCDLM147eTS+uSXv5dRzJyFn+o0tazA==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.0", + "detab": "^2.0.0", + "mdast-util-definitions": "^1.2.0", + "mdurl": "^1.0.1", + "trim": "0.0.1", + "trim-lines": "^1.0.0", + "unist-builder": "^1.0.1", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.0", + "xtend": "^4.0.1" + } }, "mdast-util-to-string": { "version": "1.0.6", @@ -7054,6 +10194,12 @@ "resolved": "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-3.1.0.tgz", "integrity": "sha512-Za0hqL1PqWrvxGtA/3NH9D5nhGAUS9grMM4obEAz5+zsk1RIw/vWUchkaoDLNdrwk05A0CSC5eEXng36/1qE5w==", "dev": true, + "requires": { + "github-slugger": "^1.2.1", + "mdast-util-to-string": "^1.0.5", + "unist-util-is": "^2.1.2", + "unist-util-visit": "^1.1.0" + }, "dependencies": { "emoji-regex": { "version": "6.1.1", @@ -7065,7 +10211,10 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.2.1.tgz", "integrity": "sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==", - "dev": true + "dev": true, + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } }, "unist-util-is": { "version": "2.1.3", @@ -7092,6 +10241,11 @@ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, "dependencies": { "p-is-promise": { "version": "2.1.0", @@ -7105,13 +10259,27 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "memorystream": { "version": "0.3.1", @@ -7124,36 +10292,70 @@ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, "dependencies": { "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -7165,19 +10367,31 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -7191,7 +10405,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "methods": { "version": "1.1.2", @@ -7203,13 +10420,32 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } }, "mime": { "version": "1.6.0", @@ -7227,7 +10463,10 @@ "version": "2.1.24", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true + "dev": true, + "requires": { + "mime-db": "1.40.0" + } }, "mimic-fn": { "version": "2.1.0", @@ -7257,7 +10496,10 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "1.2.0", @@ -7270,6 +10512,10 @@ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, "dependencies": { "is-extendable": { "version": "1.0.1", @@ -7284,6 +10530,9 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "requires": { + "minimist": "0.0.8" + }, "dependencies": { "minimist": { "version": "0.0.8", @@ -7298,6 +10547,19 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, "dependencies": { "commander": { "version": "2.15.1", @@ -7309,7 +10571,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "diff": { "version": "3.5.0", @@ -7321,7 +10586,15 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "he": { "version": "1.1.1", @@ -7339,7 +10612,10 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -7348,18 +10624,47 @@ "resolved": "https://registry.npmjs.org/module-deps-sortable/-/module-deps-sortable-4.0.6.tgz", "integrity": "sha1-ElGkuixEqS32mJvQKdoSGk8hCbA=", "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "concat-stream": "~1.5.0", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.3", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, "dependencies": { "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, "dependencies": { "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } } } }, @@ -7388,12 +10693,18 @@ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, "dependencies": { "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } }, "isarray": { "version": "0.0.1", @@ -7405,7 +10716,13 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -7438,7 +10755,20 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } }, "natural-compare": { "version": "1.4.0", @@ -7481,6 +10811,13 @@ "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz", "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==", "dev": true, + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + }, "dependencies": { "@sinonjs/formatio": { "version": "3.2.1", @@ -7500,19 +10837,53 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, "dependencies": { "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } }, "punycode": { "version": "1.4.1", @@ -7526,19 +10897,31 @@ "version": "1.1.26", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==", - "dev": true + "dev": true, + "requires": { + "semver": "^5.3.0" + } }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true + "dev": true, + "requires": { + "abbrev": "1" + } }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } }, "normalize-path": { "version": "3.0.0", @@ -7550,13 +10933,22 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } }, "now-and-later": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.2" + } }, "npm-install-package": { "version": "2.1.0", @@ -7568,13 +10960,27 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + } }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true + "dev": true, + "requires": { + "path-key": "^2.0.0" + } }, "null-check": { "version": "1.0.0", @@ -7585,8 +10991,7 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.9.0", @@ -7611,18 +11016,29 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -7636,43 +11052,73 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.0" + } }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, "dependencies": { "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true + "dev": true, + "requires": { + "for-in": "^1.0.1" + } } } }, @@ -7680,37 +11126,59 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "object.reduce": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "object.values": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true + "dev": true, + "requires": { + "ee-first": "1.1.1" + } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + }, "dependencies": { "mimic-fn": { "version": "1.2.0", @@ -7730,13 +11198,20 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, "dependencies": { "minimist": { "version": "0.0.10", @@ -7756,13 +11231,24 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } }, "ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } }, "os-browserify": { "version": "0.3.0", @@ -7780,7 +11266,12 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } }, "os-tmpdir": { "version": "1.0.2", @@ -7816,19 +11307,28 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true + "dev": true, + "requires": { + "p-try": "^2.0.0" + } }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } }, "p-try": { "version": "2.2.0", @@ -7846,19 +11346,37 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } }, "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", - "dev": true + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } }, "parse-domain": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.1.tgz", "integrity": "sha512-k/tkc7tfcoGfaUOCG5DuPNX+dt6UBqRWU9EtR0rA9esi5GpOY0OGEgprfylmYx8pykQbdBTYHLaM/UwFHXuZKA==", "dev": true, + "requires": { + "chai": "^4.2.0", + "got": "^8.3.2", + "mkdirp": "^0.5.1", + "mocha": "^6.1.4", + "npm-run-all": "^4.1.5" + }, "dependencies": { "ansi-regex": { "version": "4.1.0", @@ -7870,7 +11388,10 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "diff": { "version": "3.5.0", @@ -7882,13 +11403,46 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "mocha": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", - "dev": true + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + } }, "ms": { "version": "2.1.1", @@ -7900,25 +11454,49 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "yargs": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + } } } }, @@ -7926,25 +11504,47 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } }, "parse-git-config": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-0.2.0.tgz", "integrity": "sha1-Jygz/dFf6hRvt10zbSNrljtv9wY=", - "dev": true + "dev": true, + "requires": { + "ini": "^1.3.3" + } }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, "dependencies": { "is-extglob": { "version": "1.0.0", @@ -7956,7 +11556,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } } } }, @@ -7964,7 +11567,11 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } }, "parse-node-version": { "version": "1.0.1", @@ -7982,25 +11589,41 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-3.0.4.tgz", "integrity": "sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw==", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } }, "parse-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-3.0.2.tgz", "integrity": "sha1-YCeHpwY6eV1yuGcxl1BecvYGEL4=", - "dev": true + "dev": true, + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^1.9.1", + "parse-path": "^3.0.1", + "protocols": "^1.4.0" + } }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseuri": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } }, "parseurl": { "version": "1.3.3", @@ -8066,7 +11689,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } }, "path-root-regex": { "version": "0.1.2", @@ -8079,6 +11705,9 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "dev": true, + "requires": { + "isarray": "0.0.1" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -8093,6 +11722,9 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, + "requires": { + "pify": "^3.0.0" + }, "dependencies": { "pify": { "version": "3.0.0", @@ -8112,13 +11744,23 @@ "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true + "dev": true, + "requires": { + "through": "~2.3" + } }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "pbkdf2-compat": { "version": "2.0.1", @@ -8154,25 +11796,40 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true + "dev": true, + "requires": { + "find-up": "^3.0.0" + } }, "plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, "dependencies": { "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } } } }, @@ -8252,7 +11909,11 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } }, "prr": { "version": "1.0.1", @@ -8264,7 +11925,10 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz", "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", - "dev": true + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } }, "pseudomap": { "version": "1.0.2", @@ -8282,25 +11946,46 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, "dependencies": { "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } } } }, @@ -8332,7 +12017,11 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "querystring": { "version": "0.2.0", @@ -8357,6 +12046,11 @@ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -8370,13 +12064,20 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } }, "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } }, "range-parser": { "version": "1.2.1", @@ -8389,6 +12090,10 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, "dependencies": { "string_decoder": { "version": "0.10.31", @@ -8402,37 +12107,59 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } }, "read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, "dependencies": { "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "dev": true, + "requires": { + "p-try": "^1.0.0" + } }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-try": { "version": "1.0.0", @@ -8446,25 +12173,46 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true + "dev": true, + "requires": { + "resolve": "^1.1.6" + } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } }, "regenerate": { "version": "1.4.0", @@ -8476,7 +12224,10 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } }, "regenerator-runtime": { "version": "0.11.1", @@ -8487,19 +12238,29 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", - "dev": true + "dev": true, + "requires": { + "private": "^0.1.6" + } }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } }, "regexp-tree": { "version": "0.1.11", @@ -8517,7 +12278,15 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } }, "regjsgen": { "version": "0.5.0", @@ -8530,6 +12299,9 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", @@ -8543,61 +12315,129 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true + "dev": true, + "requires": { + "remark-parse": "^5.0.0", + "remark-stringify": "^5.0.0", + "unified": "^6.0.0" + } }, "remark-html": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-7.0.0.tgz", "integrity": "sha512-jqRzkZXCkM12gIY2ibMLTW41m7rfanliMTVQCFTezHJFsbH00YaTox/BX4gU+f/zCdzfhFJONtebFByvpMv37w==", - "dev": true + "dev": true, + "requires": { + "hast-util-sanitize": "^1.0.0", + "hast-util-to-html": "^3.0.0", + "mdast-util-to-hast": "^3.0.0", + "xtend": "^4.0.1" + } }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } }, "remark-reference-links": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-4.0.4.tgz", "integrity": "sha512-+2X8hwSQqxG4tvjYZNrTcEC+bXp8shQvwRGG6J/rnFTvBoU4G0BBviZoqKGZizLh/DG+0gSYhiDDWCqyxXW1iQ==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.0.0" + } }, "remark-slug": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-5.1.2.tgz", "integrity": "sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A==", - "dev": true + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^1.0.0" + } }, "remark-stringify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true + "dev": true, + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } }, "remark-toc": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/remark-toc/-/remark-toc-5.1.1.tgz", "integrity": "sha512-vCPW4YOsm2CfyuScdktM9KDnJXVHJsd/ZeRtst+dnBU3B3KKvt8bc+bs5syJjyptAHfqo7H+5Uhz+2blWBfwow==", - "dev": true + "dev": true, + "requires": { + "mdast-util-toc": "^3.0.0", + "remark-slug": "^5.0.0" + } }, "remote-origin-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/remote-origin-url/-/remote-origin-url-0.4.0.tgz", "integrity": "sha1-TT4pAvNOLTfRwmPYdxC3frQIajA=", - "dev": true + "dev": true, + "requires": { + "parse-git-config": "^0.2.0" + } }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } }, "remove-bom-stream": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } }, "remove-trailing-separator": { "version": "1.1.0", @@ -8621,7 +12461,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } }, "replace-ext": { "version": "1.0.0", @@ -8633,31 +12476,72 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } }, "replacestream": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } }, "request-promise": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", - "dev": true + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } }, "request-promise-core": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.11" + } }, "require-directory": { "version": "2.1.1", @@ -8676,6 +12560,10 @@ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, "dependencies": { "resolve-from": { "version": "1.0.1", @@ -8695,13 +12583,20 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } }, "resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } }, "resolve-from": { "version": "5.0.0", @@ -8713,7 +12608,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } }, "resolve-url": { "version": "0.2.1", @@ -8725,13 +12623,20 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } }, "ret": { "version": "0.1.15", @@ -8755,7 +12660,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true + "dev": true, + "requires": { + "align-text": "^0.1.1" + } }, "rimraf": { "version": "2.2.8", @@ -8767,13 +12675,20 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } }, "rx-lite": { "version": "4.0.8", @@ -8785,7 +12700,10 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true + "dev": true, + "requires": { + "rx-lite": "*" + } }, "safe-buffer": { "version": "5.1.2", @@ -8803,7 +12721,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true + "dev": true, + "requires": { + "ret": "~0.1.10" + } }, "safer-buffer": { "version": "2.1.2", @@ -8821,7 +12742,10 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true + "dev": true, + "requires": { + "ajv": "^5.0.0" + } }, "semver": { "version": "5.7.0", @@ -8833,19 +12757,40 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "mime": { "version": "1.4.1", @@ -8872,12 +12817,24 @@ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -8892,12 +12849,21 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "requires": { + "ms": "2.0.0" + }, "dependencies": { "ms": { "version": "2.0.0", @@ -8911,7 +12877,14 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } }, "ms": { "version": "2.1.1", @@ -8923,7 +12896,22 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + } }, "setprototypeof": { "version": "1.1.1", @@ -8944,6 +12932,12 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", @@ -8969,13 +12963,20 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } }, "shebang-regex": { "version": "1.0.0", @@ -8987,13 +12988,24 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } }, "signal-exit": { "version": "3.0.2", @@ -9006,6 +13018,15 @@ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "dev": true, + "requires": { + "@sinonjs/formatio": "^2.0.0", + "diff": "^3.1.0", + "lodash.get": "^4.4.2", + "lolex": "^2.2.0", + "nise": "^1.2.0", + "supports-color": "^5.1.0", + "type-detect": "^4.0.5" + }, "dependencies": { "diff": { "version": "3.5.0", @@ -9025,31 +13046,53 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "ms": { "version": "2.0.0", @@ -9064,30 +13107,49 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -9096,12 +13158,18 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -9110,12 +13178,23 @@ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -9136,6 +13215,22 @@ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -9147,7 +13242,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -9162,6 +13260,11 @@ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, "dependencies": { "component-emitter": { "version": "1.2.1", @@ -9173,7 +13276,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "isarray": { "version": "2.0.1", @@ -9193,7 +13299,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } }, "source-list-map": { "version": "2.0.1", @@ -9211,13 +13320,23 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true + "dev": true, + "requires": { + "source-map": "^0.5.6" + } }, "source-map-url": { "version": "0.4.0", @@ -9241,7 +13360,11 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-exceptions": { "version": "2.2.0", @@ -9253,7 +13376,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-license-ids": { "version": "3.0.5", @@ -9265,13 +13392,19 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true + "dev": true, + "requires": { + "through": "2" + } }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } }, "sprintf-js": { "version": "1.0.3", @@ -9283,7 +13416,18 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } }, "stack-trace": { "version": "0.0.10", @@ -9302,12 +13446,19 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } } } }, @@ -9328,6 +13479,9 @@ "resolved": "https://registry.npmjs.org/stream-array/-/stream-array-1.1.2.tgz", "integrity": "sha1-nl9zRfITfDDuO0mLkRToC1K7frU=", "dev": true, + "requires": { + "readable-stream": "~2.1.0" + }, "dependencies": { "process-nextick-args": { "version": "1.0.7", @@ -9339,7 +13493,16 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true + "dev": true, + "requires": { + "buffer-shims": "^1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } }, "string_decoder": { "version": "0.10.31", @@ -9353,19 +13516,30 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } }, "stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } }, "stream-exhaust": { "version": "1.0.2", @@ -9377,7 +13551,14 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } }, "stream-shift": { "version": "1.0.0", @@ -9390,12 +13571,21 @@ "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -9405,12 +13595,6 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true - }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -9422,6 +13606,10 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -9433,7 +13621,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -9441,19 +13632,41 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "stringify-entities": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true + "dev": true, + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-bom": { "version": "3.0.0", @@ -9477,7 +13690,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } }, "strip-json-comments": { "version": "2.0.1", @@ -9489,25 +13705,43 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true + "dev": true, + "requires": { + "minimist": "^1.1.0" + } }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "sver-compat": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } }, "tapable": { "version": "0.2.9", @@ -9519,19 +13753,34 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } }, "temp-fs": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", "dev": true, + "requires": { + "rimraf": "~2.5.2" + }, "dependencies": { "rimraf": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.5" + } } } }, @@ -9539,7 +13788,13 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", - "dev": true + "dev": true, + "requires": { + "duplexify": "^3.5.0", + "fork-stream": "^0.0.4", + "merge-stream": "^1.0.0", + "through2": "^2.0.1" + } }, "text-table": { "version": "0.2.0", @@ -9563,13 +13818,21 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } }, "through2-filter": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } }, "time-stamp": { "version": "1.1.0", @@ -9587,25 +13850,43 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } }, "tiny-lr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", "dev": true, + "requires": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + }, "dependencies": { "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true + "dev": true, + "requires": { + "ms": "^2.1.1" + } } } }, @@ -9613,13 +13894,20 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } }, "to-array": { "version": "0.1.4", @@ -9650,12 +13938,18 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -9663,19 +13957,32 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } }, "to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true + "dev": true, + "requires": { + "through2": "^2.0.3" + } }, "toidentifier": { "version": "1.0.0", @@ -9688,6 +13995,10 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, "dependencies": { "punycode": { "version": "1.4.1", @@ -9749,7 +14060,10 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } }, "tweetnacl": { "version": "0.14.5", @@ -9767,7 +14081,10 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } }, "type-detect": { "version": "4.0.8", @@ -9779,7 +14096,11 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } }, "typedarray": { "version": "0.0.6", @@ -9792,6 +14113,10 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -9812,6 +14137,11 @@ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + }, "dependencies": { "camelcase": { "version": "1.2.1", @@ -9823,13 +14153,23 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } }, "wordwrap": { "version": "0.0.2", @@ -9841,7 +14181,13 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -9861,7 +14207,18 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } }, "undertaker-registry": { "version": "1.0.1", @@ -9873,7 +14230,11 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", @@ -9885,7 +14246,11 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } }, "unicode-match-property-value-ecmascript": { "version": "1.1.0", @@ -9903,25 +14268,46 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } }, "unist-builder": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-1.0.4.tgz", "integrity": "sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg==", - "dev": true + "dev": true, + "requires": { + "object-assign": "^4.1.0" + } }, "unist-util-generated": { "version": "1.1.4", @@ -9945,7 +14331,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz", "integrity": "sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit": "^1.1.0" + } }, "unist-util-stringify-position": { "version": "1.1.2", @@ -9957,13 +14346,19 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true + "dev": true, + "requires": { + "unist-util-visit-parents": "^2.0.0" + } }, "unist-util-visit-parents": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true + "dev": true, + "requires": { + "unist-util-is": "^3.0.0" + } }, "unpipe": { "version": "1.0.0", @@ -9976,18 +14371,30 @@ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, "dependencies": { "has-value": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, "dependencies": { "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true + "dev": true, + "requires": { + "isarray": "1.0.0" + } } } }, @@ -10009,7 +14416,10 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true + "dev": true, + "requires": { + "punycode": "^2.1.0" + } }, "urix": { "version": "0.1.0", @@ -10022,6 +14432,10 @@ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", @@ -10042,6 +14456,10 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + }, "dependencies": { "querystringify": { "version": "2.1.1", @@ -10056,6 +14474,9 @@ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, + "requires": { + "prepend-http": "^2.0.0" + }, "dependencies": { "prepend-http": { "version": "2.0.0", @@ -10082,12 +14503,20 @@ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + }, "dependencies": { "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "yallist": { "version": "2.1.2", @@ -10102,6 +14531,9 @@ "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, + "requires": { + "inherits": "2.0.3" + }, "dependencies": { "inherits": { "version": "2.0.3", @@ -10133,13 +14565,20 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, "value-or-function": { "version": "3.0.0", @@ -10157,13 +14596,24 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } }, "vfile-location": { "version": "2.0.5", @@ -10175,13 +14625,23 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } }, "vfile-reporter": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-4.0.0.tgz", "integrity": "sha1-6m8K4TQvSEFXOYXgX5QXNvJ96do=", "dev": true, + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^1.0.0", + "supports-color": "^4.1.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-statistics": "^1.1.0" + }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -10193,19 +14653,30 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } } } }, @@ -10225,25 +14696,64 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } }, "vinyl-fs": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } }, "vinyl-sourcemap": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, "dependencies": { "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } } } }, @@ -10251,7 +14761,10 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true + "dev": true, + "requires": { + "source-map": "^0.5.1" + } }, "vm-browserify": { "version": "1.1.0", @@ -10269,19 +14782,32 @@ "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", - "dev": true + "dev": true, + "requires": { + "foreachasync": "^3.0.0" + } }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } }, "wdio-browserstack-service": { "version": "0.1.18", "resolved": "https://registry.npmjs.org/wdio-browserstack-service/-/wdio-browserstack-service-0.1.18.tgz", "integrity": "sha512-6tISYMKzwr2oxx0yi2Q4GoFC2Mbq81iHhqxayacC4XgFR7QbmQkxwV8JPeq590AXhuhPqqmyuEGkMqc9fo/UoQ==", - "dev": true + "dev": true, + "requires": { + "browserstack-local": "^1.3.7", + "request": "^2.81.0", + "request-promise": "^4.2.1" + } }, "wdio-concise-reporter": { "version": "0.1.2", @@ -10299,25 +14825,64 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/wdio-mocha-framework/-/wdio-mocha-framework-0.6.4.tgz", "integrity": "sha512-GZsXwoW60/fkkfqZJR/ZAdiALaM+hW+BbnTT9x214qPR4Pe5XeyYxhJNEdyf0dNI9625cMdkyZYaWoFHN5zDcA==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.23.0", + "mocha": "^5.2.0", + "wdio-sync": "0.7.3" + } }, "wdio-spec-reporter": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/wdio-spec-reporter/-/wdio-spec-reporter-0.1.5.tgz", "integrity": "sha512-MqvgTow8hFwhFT47q67JwyJyeynKodGRQCxF7ijKPGfsaG1NLssbXYc0JhiL7SiAyxnQxII0UxzTCd3I6sEdkg==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "~6.26.0", + "chalk": "^2.3.0", + "humanize-duration": "~3.15.0" + } }, "wdio-sync": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/wdio-sync/-/wdio-sync-0.7.3.tgz", "integrity": "sha512-ukASSHOQmOxaz5HTILR0jykqlHBtAPsBpMtwhpiG0aW9uc7SO7PF+E5LhVvTG4ypAh+UGmY3rTjohOsqDr39jw==", - "dev": true + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "fibers": "^3.0.0", + "object.assign": "^4.0.3" + } }, "webdriverio": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", "dev": true, + "requires": { + "archiver": "~2.1.0", + "babel-runtime": "^6.26.0", + "css-parse": "^2.0.0", + "css-value": "~0.0.1", + "deepmerge": "~2.0.1", + "ejs": "~2.5.6", + "gaze": "~1.1.2", + "glob": "~7.1.1", + "grapheme-splitter": "^1.0.2", + "inquirer": "~3.3.0", + "json-stringify-safe": "~5.0.1", + "mkdirp": "~0.5.1", + "npm-install-package": "~2.1.0", + "optimist": "~0.6.1", + "q": "~1.5.0", + "request": "^2.83.0", + "rgb2hex": "^0.1.9", + "safe-buffer": "~5.1.1", + "supports-color": "~5.0.0", + "url": "~0.11.0", + "wdio-dot-reporter": "~0.0.8", + "wgxpath": "~1.0.0" + }, "dependencies": { "has-flag": { "version": "2.0.0", @@ -10329,7 +14894,10 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } } } }, @@ -10338,12 +14906,42 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", "dev": true, + "requires": { + "acorn": "^5.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" + }, "dependencies": { "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } }, "ajv-keywords": { "version": "3.4.1", @@ -10355,7 +14953,10 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true + "dev": true, + "requires": { + "lodash": "^4.17.14" + } }, "camelcase": { "version": "4.1.0", @@ -10368,12 +14969,22 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, "dependencies": { "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -10381,13 +14992,27 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } }, "fast-deep-equal": { "version": "2.0.1", @@ -10399,7 +15024,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } }, "get-caller-file": { "version": "1.0.3", @@ -10423,7 +15051,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "json-schema-traverse": { "version": "0.4.1", @@ -10441,31 +15072,51 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -10477,19 +15128,30 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true + "dev": true, + "requires": { + "p-try": "^1.0.0" + } }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } }, "p-try": { "version": "1.0.0", @@ -10501,13 +15163,19 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true + "dev": true, + "requires": { + "pify": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -10519,13 +15187,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } }, "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } }, "require-main-filename": { "version": "1.0.1", @@ -10537,7 +15214,10 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } }, "y18n": { "version": "3.2.1", @@ -10555,13 +15235,31 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } }, "yargs-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -10570,6 +15268,21 @@ "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-walk": "^6.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.15", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, "dependencies": { "acorn": { "version": "6.2.1", @@ -10587,7 +15300,10 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } } } }, @@ -10596,6 +15312,10 @@ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, + "requires": { + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" + }, "dependencies": { "source-list-map": { "version": "0.1.8", @@ -10607,7 +15327,10 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -10616,6 +15339,15 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, + "requires": { + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" + }, "dependencies": { "mime": { "version": "2.4.4", @@ -10629,13 +15361,23 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "dev": true + "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } }, "webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, "dependencies": { "source-map": { "version": "0.6.1", @@ -10650,6 +15392,15 @@ "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-3.2.0.tgz", "integrity": "sha1-Oh0WD7EdQXJ7fObzL3IkZPmLIYY=", "dev": true, + "requires": { + "gulp-util": "^3.0.7", + "lodash.clone": "^4.3.2", + "lodash.some": "^4.2.2", + "memory-fs": "^0.3.0", + "through": "^2.3.8", + "vinyl": "^1.1.0", + "webpack": "^1.12.9" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -10661,13 +15412,20 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } }, "array-unique": { "version": "0.2.1", @@ -10685,25 +15443,41 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } }, "browserify-aes": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1" + } }, "browserify-zlib": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true + "dev": true, + "requires": { + "pako": "~0.2.0" + } }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } }, "camelcase": { "version": "1.2.1", @@ -10715,13 +15489,29 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } }, "clone": { "version": "1.0.4", @@ -10739,13 +15529,24 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "dev": true + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } }, "enhanced-resolve": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.2.0", + "tapable": "^0.1.8" + }, "dependencies": { "memory-fs": { "version": "0.2.0", @@ -10765,31 +15566,50 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } }, "expand-range": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } }, "glob-parent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } }, "has-flag": { "version": "1.0.0", @@ -10819,19 +15639,28 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true + "dev": true, + "requires": { + "isarray": "1.0.0" + } }, "json5": { "version": "0.5.1", @@ -10843,37 +15672,93 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } }, "loader-utils": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } }, "memory-fs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", - "dev": true + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } }, "node-libs-browser": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", - "dev": true + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.0", + "path-browserify": "0.0.0", + "process": "^0.11.0", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.0.5", + "stream-browserify": "^2.0.1", + "stream-http": "^2.3.1", + "string_decoder": "^0.10.25", + "timers-browserify": "^2.0.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, "os-browserify": { "version": "0.2.1", @@ -10927,7 +15812,10 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } }, "tapable": { "version": "0.1.10", @@ -10940,6 +15828,12 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, "dependencies": { "async": { "version": "0.2.10", @@ -10954,6 +15848,9 @@ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, + "requires": { + "inherits": "2.0.3" + }, "dependencies": { "inherits": { "version": "2.0.3", @@ -10967,19 +15864,32 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true + "dev": true, + "requires": { + "indexof": "0.0.1" + } }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", "dev": true, + "requires": { + "async": "^0.9.0", + "chokidar": "^1.0.0", + "graceful-fs": "^4.1.2" + }, "dependencies": { "async": { "version": "0.9.2", @@ -10993,7 +15903,24 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true + "dev": true, + "requires": { + "acorn": "^3.0.0", + "async": "^1.3.0", + "clone": "^1.0.2", + "enhanced-resolve": "~0.9.0", + "interpret": "^0.6.4", + "loader-utils": "^0.2.11", + "memory-fs": "~0.3.0", + "mkdirp": "~0.5.0", + "node-libs-browser": "^0.7.0", + "optimist": "~0.6.0", + "supports-color": "^3.1.0", + "tapable": "~0.1.8", + "uglify-js": "~2.7.3", + "watchpack": "^0.2.1", + "webpack-core": "~0.6.9" + } }, "wordwrap": { "version": "0.0.2", @@ -11005,7 +15932,13 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } } } }, @@ -11013,7 +15946,12 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "dev": true + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } }, "websocket-extensions": { "version": "0.1.3", @@ -11031,7 +15969,10 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "which-module": { "version": "2.0.0", @@ -11043,7 +15984,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } }, "window-size": { "version": "0.1.0", @@ -11061,19 +16005,28 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, "dependencies": { "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "requires": { + "number-is-nan": "^1.0.0" + } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -11087,13 +16040,21 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } }, "x-is-string": { "version": "0.1.0", @@ -11135,13 +16096,22 @@ "version": "13.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } }, "yargs-unparser": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, "dependencies": { "get-caller-file": { "version": "1.0.3", @@ -11159,13 +16129,31 @@ "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } }, "yargs-parser": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -11179,7 +16167,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true + "dev": true, + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } } } } diff --git a/test/spec/modules/buzzoolaBidAdapter_spec.js b/test/spec/modules/buzzoolaBidAdapter_spec.js new file mode 100644 index 00000000000..e6f22d1da20 --- /dev/null +++ b/test/spec/modules/buzzoolaBidAdapter_spec.js @@ -0,0 +1,279 @@ +import {expect} from 'chai'; +import {spec} from 'modules/buzzoolaBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {executeRenderer, Renderer} from '../../../src/Renderer'; +import {deepClone} from '../../../src/utils'; + +const ENDPOINT = 'https://exchange.buzzoola.com/ssp/prebidjs'; +const RENDERER_SRC = 'https://tube.buzzoola.com/new/build/buzzlibrary.js'; + +const INVALID_BIDS = [{ + 'bidder': 'buzzoola', + 'mediaTypes': {'banner': {'sizes': [[240, 400], [300, 600]]}}, + 'sizes': [[240, 400], [300, 600]] +}, { + 'bidder': 'buzzoola', + 'params': {'placementId': 417846}, + 'sizes': [[240, 400], [300, 600]] +}, { + 'bidder': 'buzzoola', + 'mediaTypes': { + 'video': { + 'playerSize': [[640, 380]], + 'mimes': ['video/mp4'], + 'minduration': 1, + 'maxduration': 2 + } + } +}, { + 'bidder': 'buzzoola', + 'params': {'placementId': 417845} +}]; + +const BANNER_BID = { + 'bidder': 'buzzoola', + 'params': {'placementId': 417846}, + 'mediaTypes': {'banner': {'sizes': [[240, 400], [300, 600]]}}, + 'sizes': [[240, 400], [300, 600]], + 'bidId': '2a11641ada3c6a' +}; + +const BANNER_BID_REQUEST = { + bidderCode: 'buzzoola', + bids: [BANNER_BID] +}; + +const BANNER_RESPONSE = [{ + 'requestId': '2a11641ada3c6a', + 'cpm': 5.583115, + 'width': 240, + 'height': 400, + 'creativeId': '11773', + 'dealId': '', + 'currency': 'RUB', + 'netRevenue': true, + 'ttl': 10800, + 'ad': '
', + 'mediaType': 'banner' +}]; + +const REQUIRED_BANNER_FIELDS = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'ad', + 'ttl', + 'creativeId', + 'netRevenue', + 'currency', + 'mediaType' +]; + +const VIDEO_BID = { + 'bidder': 'buzzoola', + 'params': {'placementId': 417845}, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': [[640, 380]], + 'mimes': ['video/mp4'], + 'minduration': 1, + 'maxduration': 2 + } + }, + 'bidId': '325a54271dc40a' +}; + +const VIDEO_BID_REQUEST = { + bidderCode: 'buzzoola', + bids: [VIDEO_BID] +}; + +const VIDEO_RESPONSE = [{ + 'requestId': '325a54271dc40a', + 'cpm': 4.6158956756756755, + 'width': 640, + 'height': 380, + 'creativeId': '11774', + 'dealId': '', + 'currency': 'RUB', + 'netRevenue': true, + 'ttl': 10800, + 'ad': '{"crs":[{"advertiser_id":165,"title":"qa//PrebidJStestVideoURL","description":"qa//PrebidJStest","duration":0,"ya_id":"55038886","raw_content":"{\\"main_content\\": \\"https://tube.buzzoola.com/xstatic/o42/mcaug/2.mp4\\"}","content":{"main_content":"https://tube.buzzoola.com/xstatic/o42/mcaug/2.mp4"},"content_type":"video_url","sponsor_link":"","sponsor_name":"","overlay":"","overlay_start_after":0,"overlay_close_after":0,"action_button_title":"","tracking_url":{},"iframe_domains":[],"soc_share_url":"https://tube.buzzoola.com/share.html","player_show_skip_button_before_play":false,"player_show_skip_button_seconds":5,"player_show_title":true,"player_data_attributes":{"expandable":"default","overroll":"default"},"click_event_view":"default","share_panel_position":"left","auto_play":true,"logo_url":{},"share_buttons":["vkontakte","facebook","twitter","moimir","odnoklassniki","embed"],"player_show_panels":false,"thumbnail":"","tracking_js":{},"click_event_url":"https://exchange.buzzoola.com/event/f9382ceb-49c2-4683-50d8-5c516c53cd69/14795a96-6261-49dc-7241-207333ab1490/m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm/click/0/","vpaid_js_url":"https://tube.buzzoola.com/new/js/lib/vpaid_js_proxy.js","skip_clickthru":false,"landing_link_text":"","sound_enabled_by_default":false,"landing_link_position":"right","displayed_price":"","js_wrapper_url":"","enable_moat":false,"branding_template":"","event_url":"https://exchange.buzzoola.com/event/f9382ceb-49c2-4683-50d8-5c516c53cd69/14795a96-6261-49dc-7241-207333ab1490/m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm/","resend_event_url":"https://exchange.buzzoola.com/resend_event/f9382ceb-49c2-4683-50d8-5c516c53cd69/14795a96-6261-49dc-7241-207333ab1490/m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm/","creative_hash":"m7JVQI9Y7J35_gEDugNO2bIiP2qTqPKfuLrqqh_LoJu0tD6PoLEglMXUBzVpSg75c-unsaijXpIERGosa1adogXgqjDml4Pm","custom_html":"","custom_js":"","height":0,"width":0,"campaign_id":5758,"line_item_id":17319,"creative_id":11774,"extra":{"imp_id":"14795a96-6261-49dc-7241-207333ab1490","rtime":"2019-08-27 13:58:36"},"subcontent":"vast","auction_settings":{"price":"4.6158956756756755","currency":"RUB","event_name":"player_seen","time_slice":0},"hash_to_embed":"kbDH64c7yFYkSu0KCwSkoUD2bNHAnUTHBERqLGtWnaIF4Kow5peD5g","need_ad":false}],"tracking_urls":{"ctor":["https://www.tns-counter.ru/V13a****buzzola_com/ru/CP1251/tmsec=buzzola_total/1322650417245790778","https://www.tns-counter.ru/V13a****buzzoola_kz/ru/UTF-8/tmsec=buzzoola_video/5395765100939533275","https://buzzoolaru.solution.weborama.fr/fcgi-bin/dispatch.fcgi?a.A=ev&a.si=3071&a.te=37&a.aap=1&a.agi=862&a.evn=PrebidJS.test&g.ra=4581478478720298652","https://x01.aidata.io/0.gif?pid=BUZZOOLA&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://top-fwz1.mail.ru/counter?id=3026769","https://www.tns-counter.ru/V13a****buzzola_com/ru/UTF-8/tmsec=buzzola_inread/542059452789128996","https://dm.hybrid.ai/match?id=111&vid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://px.adhigh.net/p/cm/buzzoola?u=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://ssp1.rtb.beeline.ru/userbind?src=buz&ssp_user_id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://sync.upravel.com/image?source=buzzoola&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://relap.io/api/partners/bzcs.gif?uid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://x.bidswitch.net/sync?ssp=sspicyads","https://inv-nets.admixer.net/adxcm.aspx?ssp=3C5173FC-CA30-4692-9116-009C19CB1BF9&rurl=%2F%2Fexchange.buzzoola.com%2Fcookiesync%2Fdsp%2Fadmixer-video%2F%24%24visitor_cookie%24%24","https://sync.datamind.ru/cookie/accepter?source=buzzoola&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://dmp.vihub.ru/match?sysid=buz&redir=no&uid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://ad.adriver.ru/cgi-bin/rle.cgi?sid=1&ad=608223&bt=21&pid=2551979&bid=6150299&bn=6150299&rnd=1279444531737367663","https://reichelcormier.bid/point/?method=match&type=ssp&key=4677290772f9000878093d69c199bfba&id=3509&extUid=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://sync.republer.com/match?src=buzzoola&id=dbdb5b13-e719-4987-7f6a-a882322bbfce","https://sm.rtb.mts.ru/p?id=dbdb5b13-e719-4987-7f6a-a882322bbfce&ssp=buzzoola","https://cm.mgid.com/m?cdsp=371151&adu=https%3A%2F%2Fexchange.buzzoola.com%2Fcookiesync%2Fdsp%2Fmarketgid-native%2F%7Bmuidn%7D","https://dmp.gotechnology.io/dmp/syncsspdmp?sspid=122258"]},"tracking_js":{"ctor":["https://buzzoola.fraudscore.mobi/dooJ9sheeeDaZ3fe.js?s=268671&l=417845"]},"placement":{"placement_id":417845,"unit_type":"inread","unit_settings":{"align":"left","autoplay_enable_sound":false,"creatives_amount":1,"debug_mode":false,"expandable":"never","sound_control":"default","target":"","width":"100%"},"unit_settings_list":["width","sound_control","debug_mode","target","creatives_amount","expandable","container_height","align","height"]},"uuid":"dbdb5b13-e719-4987-7f6a-a882322bbfce","auction_id":"f9382ceb-49c2-4683-50d8-5c516c53cd69","env":"prod"}', + 'vastXml': '\n00:00:30', + 'mediaType': 'video' +}]; + +const RENDERER_DATA = { + data: JSON.parse(VIDEO_RESPONSE[0].ad) +}; +RENDERER_DATA.data.placement.unit_settings.width = '' + VIDEO_RESPONSE[0].width; +RENDERER_DATA.data.placement.unit_settings.height = RENDERER_DATA.data.placement.unit_settings.container_height = '' + VIDEO_RESPONSE[0].height; + +const REQUIRED_VIDEO_FIELDS = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'ad', + 'ttl', + 'creativeId', + 'netRevenue', + 'currency', + 'vastXml', + 'mediaType' +]; + +describe('buzzoolaBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(VIDEO_BID)).to.be.true; + }); + + it('should return false when required params are not passed', () => { + INVALID_BIDS.forEach(bid => { + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + }); + + describe('buildRequests', () => { + let videoBidRequests = [VIDEO_BID]; + let bannerBidRequests = [BANNER_BID]; + + const bannerRequest = spec.buildRequests(bannerBidRequests, BANNER_BID_REQUEST); + const videoRequest = spec.buildRequests(videoBidRequests, VIDEO_BID_REQUEST); + + it('sends bid request to ENDPOINT via POST', () => { + expect(videoRequest.method).to.equal('POST'); + expect(bannerRequest.method).to.equal('POST'); + }); + + it('sends bid request to correct ENDPOINT', () => { + expect(videoRequest.url).to.equal(ENDPOINT); + expect(bannerRequest.url).to.equal(ENDPOINT); + }); + + it('sends correct video bid parameters', () => { + expect(videoRequest.data).to.deep.equal(VIDEO_BID_REQUEST); + }); + + it('sends correct banner bid parameters', () => { + expect(bannerRequest.data).to.deep.equal(BANNER_BID_REQUEST); + }); + }); + + describe('interpretResponse', () => { + const noBidServerResponse = []; + const emptyResponse = ''; + + function nobidServerResponseCheck(request, response = noBidServerResponse) { + const noBidResult = spec.interpretResponse({body: response}, {data: request}); + + expect(noBidResult.length).to.equal(0); + } + + function bidServerResponseCheck(response, request, fields) { + const result = spec.interpretResponse({body: response}, {data: request}); + + expect(result).to.deep.equal(response); + result.forEach(bid => { + fields.forEach(field => { + expect(bid).to.have.own.property(field); + }) + }); + } + + it('handles video nobid responses', () => { + nobidServerResponseCheck(VIDEO_BID_REQUEST); + }); + + it('handles banner nobid responses', () => { + nobidServerResponseCheck(BANNER_BID_REQUEST); + }); + + it('handles video empty responses', () => { + nobidServerResponseCheck(VIDEO_BID_REQUEST, emptyResponse); + }); + + it('handles banner empty responses', () => { + nobidServerResponseCheck(BANNER_BID_REQUEST, emptyResponse); + }); + + it('should get correct video bid response', () => { + bidServerResponseCheck(VIDEO_RESPONSE, VIDEO_BID_REQUEST, REQUIRED_VIDEO_FIELDS); + }); + + it('should get correct banner bid response', () => { + bidServerResponseCheck(BANNER_RESPONSE, BANNER_BID_REQUEST, REQUIRED_BANNER_FIELDS); + }); + }); + + describe('outstream renderer', () => { + let result; + let renderer; + + before(() => { + const adContainer = document.createElement('div'); + adContainer.id = 'adUnitCode'; + document.body.appendChild(adContainer); + + const outstreamVideoBid = deepClone(VIDEO_BID); + outstreamVideoBid.mediaTypes.video.context = 'outstream'; + + const outstreamVideoRequest = deepClone(VIDEO_BID_REQUEST); + outstreamVideoRequest.bids = [outstreamVideoBid]; + + const scriptElement = document.createElement('div'); + + const scriptStub = sinon.stub(document, 'createElement'); + scriptStub.withArgs('script').returns(scriptElement); + + result = spec.interpretResponse({body: VIDEO_RESPONSE}, {data: outstreamVideoRequest})[0]; + renderer = result.renderer; + + result.adUnitCode = 'adUnitCode'; + + scriptElement.onload && scriptElement.onload(); + + scriptStub.restore(); + }); + + it('should add renderer for outstream video', () => { + expect(result).to.have.own.property('renderer'); + }); + + it('should be instance of Renderer', () => { + expect(renderer).to.be.instanceof(Renderer); + }); + + it('should have valid src', () => { + expect(renderer.url).to.equal(RENDERER_SRC); + }); + + it('should create player instance', () => { + window.Buzzoola = { + Core: { + install: () => {} + } + }; + const spy = sinon.spy(window.Buzzoola.Core, 'install'); + executeRenderer(renderer, result); + expect(spy.called).to.be.true; + + const spyCall = spy.getCall(0); + + expect(spyCall.args[0]).to.be.instanceof(Element); + expect(spyCall.args[1]).to.deep.equal(RENDERER_DATA); + }); + }); +}); From 2f766597e9430f80469fe178f9e61124780a47a2 Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Tue, 10 Sep 2019 11:53:10 +0530 Subject: [PATCH 217/436] E2e tests for Native and Outstream video Ad formats. (#4116) * reorganize e2e/ tests into separate directories * new test page for e2e-banner testing * add test to check if Banner Ad is getting loaded * change location of the spec files to reflect change in test/e2e directory structure * add test case to check for generation of valid targeting keys * create Native Ad test page * add test case to check validity of the targeting keys and correct rendering of the Ad * update old browser versions to new * update browser version * update title * remove console.log statements * add basic functional test for e2e outstream video ad format --- browsers.json | 26 +-- test/pages/banner.html | 2 +- test/pages/native.html | 123 +++++++++++++ test/pages/outstream.html | 168 ++++++++++++++++++ test/spec/e2e/native/basic_native_ad.spec.js | 59 ++++++ .../basic_outstream_video_ad.spec.js | 53 ++++++ 6 files changed, 417 insertions(+), 14 deletions(-) create mode 100644 test/pages/native.html create mode 100644 test/pages/outstream.html create mode 100644 test/spec/e2e/native/basic_native_ad.spec.js create mode 100644 test/spec/e2e/outstream/basic_outstream_video_ad.spec.js diff --git a/browsers.json b/browsers.json index 8604e44a7b8..9042d7d0627 100644 --- a/browsers.json +++ b/browsers.json @@ -1,17 +1,17 @@ { - "bs_edge_16_windows_10": { + "bs_edge_17_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "16.0", + "browser_version": "17.0", "device": null, "os": "Windows" }, - "bs_edge_17_windows_10": { + "bs_edge_16_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "edge", - "browser_version": "17.0", + "browser_version": "16.0", "device": null, "os": "Windows" }, @@ -23,35 +23,35 @@ "device": null, "os": "Windows" }, - "bs_chrome_72_windows_10": { + "bs_chrome_74_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "72.0", + "browser_version": "74.0", "device": null, "os": "Windows" }, - "bs_chrome_71_windows_10": { + "bs_chrome_75_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "chrome", - "browser_version": "71.0", + "browser_version": "75.0", "device": null, "os": "Windows" }, - "bs_firefox_65_windows_10": { + "bs_firefox_66_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "65.0", + "browser_version": "66.0", "device": null, "os": "Windows" }, - "bs_firefox_64_windows_10": { + "bs_firefox_67_windows_10": { "base": "BrowserStack", "os_version": "10", "browser": "firefox", - "browser_version": "64.0", + "browser_version": "67.0", "device": null, "os": "Windows" }, @@ -71,4 +71,4 @@ "device": null, "os": "OS X" } -} \ No newline at end of file +} diff --git a/test/pages/banner.html b/test/pages/banner.html index e8c30239ac0..03f3b9b9e54 100644 --- a/test/pages/banner.html +++ b/test/pages/banner.html @@ -4,7 +4,7 @@ - Prebid.js Banner Ad Unit Example + Prebid.js Banner Example diff --git a/test/pages/native.html b/test/pages/native.html new file mode 100644 index 00000000000..0823f486848 --- /dev/null +++ b/test/pages/native.html @@ -0,0 +1,123 @@ + + + + + + + Prebid.js Native Example + + + + + + + + + + + + + + + +

Prebid.js Native Ad Unit Test

+
+

No response

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

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

+

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

+

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

+
+

Prebid Outstream Video Ad

+ +
+

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

+

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

+

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

+

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

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

lemma"Connecting Advertisers and Publishers directly"

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

Prebid Freewheel Test Page

+

requireExactDuration = false

+
+
+ +
+
+
+
+

+ +

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

+ +

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

Prebid Freewheel Test Page

+

requireExactDuration = false

+
+
+ +
+
+
+
+

+ +

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

+ +

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

Prebid.js Banner Ad Unit Test

- +
diff --git a/test/pages/native.html b/test/pages/native.html index 0823f486848..f382ab8aad7 100644 --- a/test/pages/native.html +++ b/test/pages/native.html @@ -7,7 +7,7 @@ Prebid.js Native Example - + diff --git a/test/pages/outstream.html b/test/pages/outstream.html index 56e443a519b..2a0543095cd 100644 --- a/test/pages/outstream.html +++ b/test/pages/outstream.html @@ -7,7 +7,7 @@ Prebid.js Video Outstream Example - + diff --git a/test/pages/video.html b/test/pages/video.html index e040b65fe23..3fabeb14b94 100644 --- a/test/pages/video.html +++ b/test/pages/video.html @@ -16,7 +16,7 @@ - + + + + data-player-host="${urls.vlHost}">
Date: Tue, 15 Oct 2019 19:49:51 +0200 Subject: [PATCH 302/436] [Orbidder-Adapter] Add bidRequestCount and remove bid.params.keyValues (#4264) * initial orbidder version in personal github repo * use adUnits from orbidder_example.html * replace obsolete functions * forgot to commit the test * check if bidderRequest object is available * try to fix weird safari/ie issue * ebayK: add more params * update orbidderBidAdapter.md * use spec. instead of this. for consistency reasons * add bidfloor parameter to params object * fix gdpr object handling * default to consentRequired: false when not explicitly given * wip - use onSetTargeting callback * add tests for onSetTargeting callback * fix params and respective tests * remove not used bid.params.keyValues * add bidRequestCount to orbidder.otto.de/bid Post request * add bidRequestCount to test object defaultBidRequest --- modules/orbidderBidAdapter.js | 2 +- test/spec/modules/orbidderBidAdapter_spec.js | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 954ad82261f..88534ae1596 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -19,7 +19,6 @@ export const spec = { (bid.params.accountId && (typeof bid.params.accountId === 'string')) && (bid.params.placementId && (typeof bid.params.placementId === 'string')) && ((typeof bid.params.bidfloor === 'undefined') || (typeof bid.params.bidfloor === 'number')) && - ((typeof bid.params.keyValues === 'undefined') || (typeof bid.params.keyValues === 'object')) && ((typeof bid.params.profile === 'undefined') || (typeof bid.params.profile === 'object'))); }, @@ -38,6 +37,7 @@ export const spec = { auctionId: bidRequest.auctionId, transactionId: bidRequest.transactionId, adUnitCode: bidRequest.adUnitCode, + bidRequestCount: bidRequest.bidRequestCount, sizes: bidRequest.sizes, params: bidRequest.params } diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index aeaa5f30446..1b76de9841a 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -10,6 +10,7 @@ describe('orbidderBidAdapter', () => { bidId: 'd66fa86787e0b0ca900a96eacfd5f0bb', auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d8', transactionId: 'd58851660c0c4461e4aa06344fc9c0c6', + bidRequestCount: 1, adUnitCode: 'adunit-code', sizes: [[300, 250], [300, 600]], params: { @@ -46,12 +47,6 @@ describe('orbidderBidAdapter', () => { expect(spec.isBidRequestValid(defaultBidRequest)).to.equal(true); }); - it('accepts optional keyValues object', () => { - const bidRequest = deepClone(defaultBidRequest); - bidRequest.params.keyValues = {'key': 'value'}; - expect(spec.isBidRequestValid(bidRequest)).to.equal(true); - }); - it('accepts optional profile object', () => { const bidRequest = deepClone(defaultBidRequest); bidRequest.params.profile = {'key': 'value'}; @@ -64,12 +59,6 @@ describe('orbidderBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('doesn\'t accept malformed keyValues', () => { - const bidRequest = deepClone(defaultBidRequest); - bidRequest.params.keyValues = 'another not usable string'; - expect(spec.isBidRequestValid(bidRequest)).to.equal(false); - }); - it('doesn\'t accept malformed profile', () => { const bidRequest = deepClone(defaultBidRequest); bidRequest.params.profile = 'another not usable string'; From 2f68d356653f68e2d0f4f791070c9ffd5283d9ce Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Tue, 15 Oct 2019 23:23:37 +0530 Subject: [PATCH 303/436] PulsePoint: remove usage of deprecated utils method / prep for 3.0 (#4257) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * Removing usage of deprecated utils method * minor refactor --- modules/pulsepointBidAdapter.js | 12 +++--- .../spec/modules/pulsepointBidAdapter_spec.js | 42 +++++++++++-------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 9c0d67d9612..fee247ba31f 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -40,7 +40,7 @@ export const spec = { const request = { id: bidRequests[0].bidderRequestId, imp: bidRequests.map(slot => impression(slot)), - site: site(bidRequests), + site: site(bidRequests, bidderRequest), app: app(bidRequests), device: device(), bcat: bidRequests[0].params.bcat, @@ -100,7 +100,7 @@ function bidResponseAvailable(request, response) { idToBidMap[bid.impid] = bid; })); } - if (request.bidderRequest) { + if (request.bidderRequest && request.bidderRequest.bids) { request.bidderRequest.bids.forEach(bid => { idToSlotConfig[bid.bidId] = bid; }); @@ -307,16 +307,16 @@ function dataAsset(id, params, type, defaultLen) { /** * Produces an OpenRTB site object. */ -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; - const appParams = bidderRequest[0].params.app; +function site(bidRequests, bidderRequest) { + const pubId = bidRequests && bidRequests.length > 0 ? bidRequests[0].params.cp : '0'; + const appParams = bidRequests[0].params.app; if (!appParams) { return { publisher: { id: pubId.toString(), }, ref: referrer(), - page: utils.getTopWindowLocation().href, + page: bidderRequest && bidderRequest.refererInfo ? bidderRequest.refererInfo.referer : '', } } return null; diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 1d22ca6eadc..9ed6d3631f5 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -1,7 +1,7 @@ /* eslint dot-notation:0, quote-props:0 */ import {expect} from 'chai'; import {spec} from 'modules/pulsepointBidAdapter'; -import {deepClone, getTopWindowLocation} from 'src/utils'; +import {deepClone} from 'src/utils'; describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ @@ -138,9 +138,14 @@ describe('PulsePoint Adapter Tests', function () { } } }]; + const bidderRequest = { + refererInfo: { + referer: 'https://publisher.com/home' + } + }; it('Verify build request', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -149,7 +154,7 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.site.publisher).to.not.equal(null); expect(ortbRequest.site.publisher.id).to.equal('p10000'); expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.site.page).to.equal('https://publisher.com/home'); expect(ortbRequest.imp).to.have.lengthOf(2); // device object expect(ortbRequest.device).to.not.equal(null); @@ -167,7 +172,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify parse response', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); const ortbRequest = request.data; const ortbResponse = { seatbid: [{ @@ -196,7 +201,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify use ttl in ext', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); const ortbRequest = request.data; const ortbResponse = { seatbid: [{ @@ -222,13 +227,13 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify full passback', function () { - const request = spec.buildRequests(slotConfigs); + const request = spec.buildRequests(slotConfigs, bidderRequest); const bids = spec.interpretResponse({ body: null }, request) expect(bids).to.have.lengthOf(0); }); it('Verify Native request', function () { - const request = spec.buildRequests(nativeSlotConfig); + const request = spec.buildRequests(nativeSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -266,7 +271,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify Native response', function () { - const request = spec.buildRequests(nativeSlotConfig); + const request = spec.buildRequests(nativeSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -355,7 +360,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify app requests', function () { - const request = spec.buildRequests(appSlotConfig); + const request = spec.buildRequests(appSlotConfig, bidderRequest); const ortbRequest = request.data; // site object expect(ortbRequest.site).to.equal(null); @@ -368,13 +373,13 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify GDPR', function () { - const bidderRequest = { + const bidderRequestGdpr = { gdprConsent: { gdprApplies: true, consentString: 'serialized_gpdr_data' } }; - const request = spec.buildRequests(slotConfigs, bidderRequest); + const request = spec.buildRequests(slotConfigs, Object.assign({}, bidderRequest, bidderRequestGdpr)); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -389,7 +394,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify Video request', function () { - const request = spec.buildRequests(videoSlotConfig); + const request = spec.buildRequests(videoSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -409,7 +414,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify Video response', function () { - const request = spec.buildRequests(videoSlotConfig); + const request = spec.buildRequests(videoSlotConfig, bidderRequest); expect(request.url).to.equal('https://bid.contextweb.com/header/ortb?src=prebid'); expect(request.method).to.equal('POST'); const ortbRequest = request.data; @@ -433,7 +438,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify extra parameters', function () { - let request = spec.buildRequests(additionalParamsConfig); + let request = spec.buildRequests(additionalParamsConfig, bidderRequest); let ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.imp).to.have.lengthOf(1); @@ -448,7 +453,7 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.imp[0].ext.prebid.extra_key4).to.eql([1, 2, 3]); expect(Object.keys(ortbRequest.imp[0].ext.prebid)).to.eql(['extra_key1', 'extra_key2', 'extra_key3', 'extra_key4']); // attempting with a configuration with no unknown params. - request = spec.buildRequests(outstreamSlotConfig); + request = spec.buildRequests(outstreamSlotConfig, bidderRequest); ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.imp).to.have.lengthOf(1); @@ -456,7 +461,7 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify ortb parameters', function () { - const request = spec.buildRequests(ortbParamsSlotConfig); + const request = spec.buildRequests(ortbParamsSlotConfig, bidderRequest); const ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.bcat).to.eql(['IAB-1', 'IAB-20']); @@ -472,7 +477,8 @@ describe('PulsePoint Adapter Tests', function () { }); it('Verify outstream renderer', function () { - const request = spec.buildRequests(outstreamSlotConfig, {bids: [outstreamSlotConfig[0]]}); + const bidderRequestOutstream = Object.assign({}, bidderRequest, {bids: [outstreamSlotConfig[0]]}); + const request = spec.buildRequests(outstreamSlotConfig, bidderRequestOutstream); const ortbRequest = request.data; expect(ortbRequest).to.not.be.null; expect(ortbRequest.imp[0]).to.not.be.null; @@ -521,7 +527,7 @@ describe('PulsePoint Adapter Tests', function () { } } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request).to.be.not.null; const ortbRequest = request.data; expect(request.data).to.be.not.null; From 3f727d6c63e4ac733d6c89efd8a15fc7b3ce4a4c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 15 Oct 2019 13:59:18 -0400 Subject: [PATCH 304/436] Use isArray method (#4288) --- src/adapters/bidderFactory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 90cab154fd4..4ccbfd89457 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -9,7 +9,7 @@ import CONSTANTS from '../constants.json'; import events from '../events'; import includes from 'core-js/library/fn/array/includes'; import { ajax } from '../ajax'; -import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess } from '../utils'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess, isArray } from '../utils'; import { ADPOD } from '../mediaTypes'; import { getHook } from '../hook'; @@ -290,7 +290,7 @@ export function newBidder(spec) { } if (bids) { - if (bids.forEach) { + if (isArray(bids)) { bids.forEach(addBidUsingRequestMap); } else { addBidUsingRequestMap(bids); From f8fc865b56ae5efd1b7ca3413d8a08ddcc367aad Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Tue, 15 Oct 2019 15:03:09 -0500 Subject: [PATCH 305/436] Add Parrable ID submodule (#4266) * add parrable id submodule * fix integration test config * fix var name * always refresh sotredId for parrable * add submodulesThatAlwaysRefresh concept * remove comment * add parrable url as one string * add parrable prod endpoint * use .indexOf instead of .includes * add params to test config * comment failing test * uncomment failing assertion * add parrable ID to prebid server adapter * add parrableIdSystem to .submodules.json * extract parrableId unit tests from userId spec * remove breakline between imports * remove unused param * remove userId generic feature from parrableId module * remove trailing space * fix failing test due to none merged conflict --- integrationExamples/gpt/userId_example.html | 11 +++ modules/.submodules.json | 1 + modules/parrableIdSystem.js | 92 +++++++++++++++++++ modules/prebidServerBidAdapter/index.js | 11 ++- modules/userId/index.js | 1 + modules/userId/userId.md | 11 +++ test/spec/modules/parrableIdSystem_spec.js | 77 ++++++++++++++++ .../modules/prebidServerBidAdapter_spec.js | 3 + 8 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 modules/parrableIdSystem.js create mode 100644 test/spec/modules/parrableIdSystem_spec.js diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 09e9e4147fc..6d2c2ce677a 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -152,6 +152,17 @@ refreshInSeconds: 8*3600 // Refresh frequency of cookies, defaulting to 'expires' }, + }, { + name: "parrableId", + params: { + // change to Parrable Partner Client ID(s) you received from the Parrable Partners you are using + partner: '30182847-e426-4ff9-b2b5-9ca1324ea09b' + }, + storage: { + type: "cookie", + name: "_parrable_eid", // create a cookie with this name + expires: 365 // cookie can last for a year + } }, { name: "pubCommonId", storage: { diff --git a/modules/.submodules.json b/modules/.submodules.json index 81c82603083..09063deea40 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -3,6 +3,7 @@ "digiTrustIdSystem", "id5IdSystem", "criteortusIdSystem", + "parrableIdSystem", "liveIntentIdSystem" ], "adpod": [ diff --git a/modules/parrableIdSystem.js b/modules/parrableIdSystem.js new file mode 100644 index 00000000000..e8ad7f9acc1 --- /dev/null +++ b/modules/parrableIdSystem.js @@ -0,0 +1,92 @@ +/** + * This module adds Parrable to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/parrableIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils' +import {ajax} from '../src/ajax'; +import {submodule} from '../src/hook'; + +const PARRABLE_URL = 'https://h.parrable.com/prebid'; + +function isValidConfig(configParams) { + if (!configParams) { + utils.logError('User ID - parrableId submodule requires configParams'); + return false; + } + if (!configParams.partner) { + utils.logError('User ID - parrableId submodule requires partner list'); + return false; + } + return true; +} + +function fetchId(configParams, consentData, currentStoredId) { + if (!isValidConfig(configParams)) return; + + const data = { + eid: currentStoredId || null, + trackers: configParams.partner.split(',') + }; + + const searchParams = { + data: btoa(JSON.stringify(data)), + _rand: Math.random() + }; + + const options = { + method: 'GET', + withCredentials: true + }; + + const callback = function (cb) { + const onSuccess = (response) => { + let eid; + if (response) { + try { + let responseObj = JSON.parse(response); + eid = responseObj ? responseObj.eid : undefined; + } catch (error) { + utils.logError(error); + } + } + cb(eid); + }; + ajax(PARRABLE_URL, onSuccess, searchParams, options); + }; + + return { callback }; +}; + +/** @type {Submodule} */ +export const parrableIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'parrableId', + /** + * decode the stored id value for passing to bid requests + * @function + * @param {Object|string} value + * @return {(Object|undefined} + */ + decode(value) { + return (value && typeof value === 'string') ? { 'parrableid': value } : undefined; + }, + + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @param {SubmoduleParams} [configParams] + * @param {ConsentData} [consentData] + * @returns {function(callback:function)} + */ + getId(configParams, consentData, currentStoredId) { + return fetchId(configParams, consentData, currentStoredId); + } +}; + +submodule('userId', parrableIdSubmodule); diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 7776db714dd..872e0bb81d9 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -698,7 +698,7 @@ const OPEN_RTB_PROTOCOL = { } const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId'); - if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.lipb)) { + if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.parrableid || bidUserId.lipb)) { utils.deepSetValue(request, 'user.ext.eids', []); if (bidUserId.tdid) { @@ -722,6 +722,15 @@ const OPEN_RTB_PROTOCOL = { }); } + if (bidUserId.parrableid) { + request.user.ext.eids.push({ + source: 'parrable.com', + uids: [{ + id: bidUserId.parrableid + }] + }); + } + if (bidUserId.lipb && bidUserId.lipb.lipbid) { request.user.ext.eids.push({ source: 'liveintent.com', diff --git a/modules/userId/index.js b/modules/userId/index.js index baeb1e2574c..ac96fd2cec8 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -371,6 +371,7 @@ function initSubmodules(submodules, consentData) { utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); return []; } + return submodules.reduce((carry, submodule) => { // There are two submodule configuration types to handle: storage or value // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method diff --git a/modules/userId/userId.md b/modules/userId/userId.md index b5b8c216ead..9b363bbcf64 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -32,6 +32,17 @@ pbjs.setConfig({ name: "id5id", expires: 5, // Expiration of cookies in days refreshInSeconds: 8*3600 // User Id cache lifetime in seconds, defaulting to 'expires' + }, + }, { + name: 'parrableId', + params: { + // Replace the list contents with the Parrable Partner Client IDs for Parrable-aware bid adapters in use + partners: [ "30182847-e426-4ff9-b2b5-9ca1324ea09b" ] + }, + storage: { + type: 'cookie', + name: '_parrable_eid', + expires: 365 } }, { name: 'identityLink', diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js new file mode 100644 index 00000000000..540e63aa630 --- /dev/null +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -0,0 +1,77 @@ +import { expect } from 'chai'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; +import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; +import { parrableIdSubmodule } from 'modules/parrableIdSystem'; + +const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; +const P_COOKIE_NAME = '_parrable_eid'; +const P_COOKIE_VALUE = '01.1563917337.test-eid'; +const P_CONFIG_MOCK = { + name: 'parrableId', + params: { + partner: 'parrable_test_partner_123,parrable_test_partner_456' + }, + storage: { + name: '_parrable_eid', + type: 'cookie', + expires: 364 + } +}; + +describe('Parrable ID System', function() { + function getConfigMock() { + return { + userSync: { + syncDelay: 0, + userIds: [P_CONFIG_MOCK] + } + } + } + function getAdUnitMock(code = 'adUnit-code') { + return { + code, + mediaTypes: {banner: {}, native: {}}, + sizes: [ + [300, 200], + [300, 600] + ], + bids: [{ + bidder: 'sampleBidder', + params: { placementId: 'banner-only-bidder' } + }] + }; + } + + describe('Parrable ID in Bid Request', function() { + let adUnits; + + beforeEach(function() { + adUnits = [getAdUnitMock()]; + }); + + it('should append parrableid to bid request', function(done) { + // simulate existing browser local storage values + utils.setCookie( + P_COOKIE_NAME, + P_COOKIE_VALUE, + (new Date(Date.now() + 5000).toUTCString()) + ); + + setSubmoduleRegistry([parrableIdSubmodule]); + init(config); + config.setConfig(getConfigMock()); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.parrableid'); + expect(bid.userId.parrableid).to.equal(P_COOKIE_VALUE); + }); + }); + utils.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); + done(); + }, { adUnits }); + }); + }); +}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 1c10130a84e..658f130d144 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1044,6 +1044,7 @@ describe('S2S Adapter', function () { userIdBidRequest[0].bids[0].userId = { tdid: 'abc123', pubcid: '1234', + parrableid: '01.1563917337.test-eid', lipb: { lipbid: 'li-xyz' } @@ -1057,6 +1058,8 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')).is.not.empty; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')[0].uids[0].id).is.equal('01.1563917337.test-eid'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].uids[0].id).is.equal('li-xyz'); }); From 6c5ab7136e8fe03c0b263fdefa0e60d56a0b93a5 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 15 Oct 2019 16:58:50 -0400 Subject: [PATCH 306/436] Prebid 2.36.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ca06ddb8b24..fbbf5ef66d3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.36.0-pre", + "version": "2.36.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From e46ad1ab3cd28568765f80a444f31f09b36e0039 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 15 Oct 2019 17:11:39 -0400 Subject: [PATCH 307/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbbf5ef66d3..0200db4eace 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.36.0", + "version": "2.37.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 01888647aef34830ce6c0861dc46462de50eba7a Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 15 Oct 2019 15:20:11 -0700 Subject: [PATCH 308/436] Support schain module and send bidfloor param in Sharethrough adapter (#4271) * Add support for supply chain object module Story: [#168742394](https://www.pivotaltracker.com/story/show/168742394) Co-authored-by: Josh Becker * Add bidfloor parameter to bid request sent to STX Story: [#168742573](https://www.pivotaltracker.com/story/show/168742573) --- modules/sharethroughBidAdapter.js | 8 ++++ .../modules/sharethroughBidAdapter_spec.js | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index 7fe41b2b7ae..117088f5355 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -41,6 +41,14 @@ export const sharethroughAdapterSpec = { query.ttduid = bidRequest.userId.tdid; } + if (bidRequest.schain) { + query.schain = JSON.stringify(bidRequest.schain); + } + + if (bidRequest.bidfloor) { + query.bidfloor = parseFloat(bidRequest.bidfloor); + } + // Data that does not need to go to the server, // but we need as part of interpretResponse() const strData = { diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index afa5f44959c..8a8ccdbbeb3 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -280,6 +280,44 @@ describe('sharethrough adapter spec', function () { } }); }); + + it('should add a supply chain parameter if schain is present', function() { + // shallow copy of the first bidRequest obj, so we don't mutate + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest['schain'] = { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1 + } + ] + }; + + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.schain).to.eq(JSON.stringify(bidRequest.schain)); + }); + + it('should not add a supply chain parameter if schain is missing', function() { + const bidRequest = spec.buildRequests(bidRequests)[0]; + expect(bidRequest.data).to.not.include.any.keys('schain'); + }); + + it('should include the bidfloor parameter if it is present in the bid request', function() { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest['bidfloor'] = 0.50; + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data.bidfloor).to.eq(0.5); + }); + + it('should not include the bidfloor parameter if it is missing in the bid request', function() { + const bidRequest = Object.assign({}, bidRequests[0]); + const builtBidRequest = spec.buildRequests([bidRequest])[0]; + expect(builtBidRequest.data).to.not.include.any.keys('bidfloor'); + }); }); describe('.interpretResponse', function () { From f2c4cfe9d8a756fffbe68daa5fe44eff9d591151 Mon Sep 17 00:00:00 2001 From: hbanalytics <55453525+hbanalytics@users.noreply.github.com> Date: Wed, 16 Oct 2019 01:30:50 +0300 Subject: [PATCH 309/436] Platform One Analytics Adapter (#4233) * Added Y1 Analytics Adapter * rename y1AnalyticsAdapter in yieldoneAnalyticsAdapter * Yieldone Bid Adapter: fixes from lint check * Yieldone Analytics Adapter: fix endpoint protocol * Added spec file for yieldone Analytics Adapter --- modules/yieldoneAnalyticsAdapter.js | 122 +++++++++ modules/yieldoneAnalyticsAdapter.md | 21 ++ .../modules/yieldoneAnalyticsAdapter_spec.js | 256 ++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 modules/yieldoneAnalyticsAdapter.js create mode 100644 modules/yieldoneAnalyticsAdapter.md create mode 100644 test/spec/modules/yieldoneAnalyticsAdapter_spec.js diff --git a/modules/yieldoneAnalyticsAdapter.js b/modules/yieldoneAnalyticsAdapter.js new file mode 100644 index 00000000000..94dd0daa0b2 --- /dev/null +++ b/modules/yieldoneAnalyticsAdapter.js @@ -0,0 +1,122 @@ +import {ajax} from '../src/ajax'; +import adapter from '../src/AnalyticsAdapter'; +import CONSTANTS from '../src/constants.json'; +import adapterManager from '../src/adapterManager'; +import { targeting } from '../src/targeting'; +import { auctionManager } from '../src/auctionManager'; +import * as utils from '../src/utils'; + +const ANALYTICS_CODE = 'yieldone'; +const analyticsType = 'endpoint'; +// const VERSION = '1.0.0'; +const defaultUrl = '//pool.tsukiji.iponweb.net/hba'; +const requestedBidders = {}; +const requestedBids = {}; +const referrers = {}; + +let currentAuctionId = ''; +let url = defaultUrl; +let pubId = ''; + +const yieldoneAnalytics = Object.assign(adapter({analyticsType}), { + getUrl() { return url; }, + track({eventType, args = {}}) { + if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { + const reqBidderId = `${args.bidderCode}_${args.auctionId}`; + requestedBidders[reqBidderId] = utils.deepClone(args); + requestedBidders[reqBidderId].bids = []; + args.bids.forEach((bid) => { + requestedBids[`${bid.bidId}_${bid.auctionId}`] = bid; + }); + } + if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT && utils.isArray(args)) { + const eventsStorage = yieldoneAnalytics.eventsStorage; + const reqBidders = {}; + args.forEach((bid) => { + const reqBidId = `${bid.bidId}_${bid.auctionId}`; + const reqBidderId = `${bid.bidder}_${bid.auctionId}`; + if (!eventsStorage[bid.auctionId]) eventsStorage[bid.auctionId] = []; + if (requestedBidders[reqBidderId] && requestedBids[reqBidId]) { + if (!reqBidders[bid.bidder]) { + reqBidders[bid.bidder] = requestedBidders[reqBidderId]; + reqBidders[bid.bidder].pubId = pubId; + eventsStorage[bid.auctionId].push({eventType, params: reqBidders[bid.bidder]}); + delete requestedBidders[reqBidderId]; + } + reqBidders[bid.bidder].bids.push(requestedBids[reqBidId]); + delete requestedBids[reqBidId]; + } + }); + } else { + args.pubId = pubId; + currentAuctionId = args.auctionId || currentAuctionId; + if (currentAuctionId) { + const eventsStorage = yieldoneAnalytics.eventsStorage; + if (!eventsStorage[currentAuctionId]) eventsStorage[currentAuctionId] = []; + const referrer = args.refererInfo && args.refererInfo.referer; + if (referrer && referrers[currentAuctionId] !== referrer) { + referrers[currentAuctionId] = referrer; + } + eventsStorage[currentAuctionId].push({ + eventType, + params: args + }); + } + } + if ( + eventType === CONSTANTS.EVENTS.AUCTION_END || eventType === CONSTANTS.EVENTS.BID_WON + ) { + args.adServerTargeting = targeting.getAllTargeting( + auctionManager.getAdUnitCodes(), + auctionManager.getBidsReceived() + ); + if (yieldoneAnalytics.eventsStorage[args.auctionId]) { + yieldoneAnalytics.eventsStorage[args.auctionId].forEach((it) => { + it.page = {url: referrers[currentAuctionId]}; + }); + } + yieldoneAnalytics.sendStat(yieldoneAnalytics.eventsStorage[args.auctionId], args.auctionId); + } + }, + sendStat(events, auctionId) { + if (!events) return; + delete yieldoneAnalytics.eventsStorage[auctionId]; + ajax( + url, + { + success: function() {}, + error: function() {} + }, + JSON.stringify(events), + { + method: 'POST' + } + ); + } +}); + +yieldoneAnalytics.eventsStorage = {}; + +// save the base class function +yieldoneAnalytics.originEnableAnalytics = yieldoneAnalytics.enableAnalytics; + +// override enableAnalytics so we can get access to the config passed in from the page +yieldoneAnalytics.enableAnalytics = function (config) { + const options = config && config.options; + if (options) { + if (typeof options.url === 'string') { + url = options.url; + } + if (options.pubId) { + pubId = options.pubId.toString(); + } + } + yieldoneAnalytics.originEnableAnalytics(config); // call the base class function +}; + +adapterManager.registerAnalyticsAdapter({ + adapter: yieldoneAnalytics, + code: ANALYTICS_CODE +}); + +export default yieldoneAnalytics; diff --git a/modules/yieldoneAnalyticsAdapter.md b/modules/yieldoneAnalyticsAdapter.md new file mode 100644 index 00000000000..43be87b114b --- /dev/null +++ b/modules/yieldoneAnalyticsAdapter.md @@ -0,0 +1,21 @@ +# Overview +Module Name: Platform One Analytics + +Module Type: Analytics Adapter + +Maintainer: y1s@platform-one.co.jp + +# Description + +Analytics adapter for Platform One. Please contact y1s@platform-one.co.jp for any additional information. Official website link to the vendor: www.platform-one.co.jp/. + +# Test Parameters + +``` +{ + provider: 'yieldone', + options : { + pubId : 'TestAnalyticsPublisher', //id provided by Platform One publisher team + } +} +``` \ No newline at end of file diff --git a/test/spec/modules/yieldoneAnalyticsAdapter_spec.js b/test/spec/modules/yieldoneAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..a297403b2e0 --- /dev/null +++ b/test/spec/modules/yieldoneAnalyticsAdapter_spec.js @@ -0,0 +1,256 @@ +import yieldoneAnalytics from 'modules/yieldoneAnalyticsAdapter'; +import { targeting } from 'src/targeting'; +import { expect } from 'chai'; +let events = require('src/events'); +let adapterManager = require('src/adapterManager').default; +let constants = require('src/constants.json'); + +describe('Yieldone Prebid Analytic', function () { + let sendStatStub; + let getAllTargetingStub; + const fakeTargeting = { + '0000': {'someId': 'someValue'} + }; + + describe('enableAnalytics', function () { + beforeEach(function () { + sendStatStub = sinon.stub(yieldoneAnalytics, 'sendStat'); + getAllTargetingStub = sinon.stub(targeting, 'getAllTargeting').returns(fakeTargeting); + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(function () { + sendStatStub.restore(); + getAllTargetingStub.restore(); + events.getEvents.restore(); + }); + + after(function () { + yieldoneAnalytics.disableAnalytics(); + }); + + it('should catch all events', function (done) { + adapterManager.registerAnalyticsAdapter({ + code: 'yieldone', + adapter: yieldoneAnalytics + }); + + const initOptions = { + pubId: '123456' + }; + + const auctionId = 'test-test-test'; + const testReferrer = 'http://test'; + + const request = [ + { + bidderCode: 'biddertest_1', + auctionId: auctionId, + refererInfo: {referer: testReferrer}, + bids: [ + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '1234', + bidder: 'biddertest_1', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param1: '111', param2: '222'}, + sizes: [[300, 250], [336, 280]] + }, + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '5678', + bidder: 'biddertest_1', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param1: '222', param2: '222'}, + sizes: [[300, 250], [336, 280]] + } + ] + }, + { + bidderCode: 'biddertest_2', + auctionId: auctionId, + refererInfo: {referer: testReferrer}, + bids: [ + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '91011', + bidder: 'biddertest_2', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {paramA: '111', paramB: '222'}, + sizes: [[300, 250], [336, 280]] + } + ] + }, + { + bidderCode: 'biddertest_3', + auctionId: auctionId, + refererInfo: {referer: testReferrer}, + bids: [ + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '12131', + bidder: 'biddertest_3', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param_1: '111', param_2: '222'}, + sizes: [[300, 250], [336, 280]] + } + ] + } + ]; + + const responses = [ + { + width: 300, + height: 250, + statusMessage: 'Bid available', + bidId: '1234', + auctionId: auctionId, + cpm: 0.1, + bidder: 'biddertest_1', + adUnitCode: '0000', + timeToRespond: 100 + }, + { + width: 336, + height: 280, + statusMessage: 'Bid available', + bidId: '5678', + auctionId: auctionId, + cpm: 0.2, + bidder: 'biddertest_1', + adUnitCode: '0000', + timeToRespond: 100 + }, + { + width: 300, + height: 250, + statusMessage: 'Bid available', + bidId: '91011', + auctionId: auctionId, + cpm: 0.3, + bidder: 'biddertest_2', + adUnitCode: '0000', + timeToRespond: 100 + }, + { + bidId: '12131', + auctionId: auctionId, + bidder: 'biddertest_3' + } + ]; + + const winner = { + width: 300, + height: 250, + statusMessage: 'Bid available', + bidId: '91011', + auctionId: auctionId, + cpm: 0.3, + bidder: 'biddertest_2', + adUnitCode: '0000', + timeToRespond: 100 + }; + + const expectedEvents = [ + { + eventType: constants.EVENTS.AUCTION_INIT, + page: {url: testReferrer}, + params: { + config: initOptions, + auctionId: auctionId, + pubId: initOptions.pubId + } + }, + { + eventType: constants.EVENTS.BID_REQUESTED, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[0]) + }, + { + eventType: constants.EVENTS.BID_REQUESTED, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[1]) + }, + { + eventType: constants.EVENTS.BID_REQUESTED, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[2]) + }, + { + eventType: constants.EVENTS.BID_RESPONSE, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, responses[0]) + }, + { + eventType: constants.EVENTS.BID_RESPONSE, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, responses[1]) + }, + { + eventType: constants.EVENTS.BID_RESPONSE, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, responses[2]) + }, + { + eventType: constants.EVENTS.BID_TIMEOUT, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId}, request[2]) + }, + { + eventType: constants.EVENTS.AUCTION_END, + page: {url: testReferrer}, + params: { + auctionId: auctionId, + pubId: initOptions.pubId, + adServerTargeting: fakeTargeting + } + } + ]; + + const wonExpectedEvents = [ + { + eventType: constants.EVENTS.BID_WON, + page: {url: testReferrer}, + params: Object.assign({pubId: initOptions.pubId, adServerTargeting: fakeTargeting}, winner) + } + ]; + + adapterManager.enableAnalytics({ + provider: 'yieldone', + options: initOptions + }); + + events.emit(constants.EVENTS.AUCTION_INIT, {config: initOptions, auctionId: auctionId}); + + events.emit(constants.EVENTS.BID_REQUESTED, request[0]); + events.emit(constants.EVENTS.BID_REQUESTED, request[1]); + events.emit(constants.EVENTS.BID_REQUESTED, request[2]); + + events.emit(constants.EVENTS.BID_RESPONSE, responses[0]); + events.emit(constants.EVENTS.BID_RESPONSE, responses[1]); + events.emit(constants.EVENTS.BID_RESPONSE, responses[2]); + + events.emit(constants.EVENTS.BID_TIMEOUT, [responses[3]]); + + events.emit(constants.EVENTS.AUCTION_END, {auctionId: auctionId}); + + expect(yieldoneAnalytics.eventsStorage[auctionId]).to.deep.equal(expectedEvents); + + delete yieldoneAnalytics.eventsStorage[auctionId]; + + setTimeout(function() { + events.emit(constants.EVENTS.BID_WON, winner); + + sinon.assert.callCount(sendStatStub, 2); + expect(yieldoneAnalytics.eventsStorage[auctionId]).to.deep.equal(wonExpectedEvents); + + delete yieldoneAnalytics.eventsStorage[auctionId]; + done(); + }, 1000); + }); + }); +}); From bbc9252cc3678bad8c481e201da78fc09e22e0e2 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Wed, 16 Oct 2019 09:07:40 -0500 Subject: [PATCH 310/436] Fix parrable id integration example (#4317) * fix parrableId integration example * add parentheses --- modules/userId/userId.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 9b363bbcf64..b10aa2adc20 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -36,8 +36,8 @@ pbjs.setConfig({ }, { name: 'parrableId', params: { - // Replace the list contents with the Parrable Partner Client IDs for Parrable-aware bid adapters in use - partners: [ "30182847-e426-4ff9-b2b5-9ca1324ea09b" ] + // Replace partner with comma-separated (if more than one) Parrable Partner Client ID(s) for Parrable-aware bid adapters in use + partner: "30182847-e426-4ff9-b2b5-9ca1324ea09b" }, storage: { type: 'cookie', From 31d78950e9c14763dc2520320749863c30895d43 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Wed, 16 Oct 2019 17:55:43 +0200 Subject: [PATCH 311/436] Improve Digital adapter: support for video (#4318) * Bid floor, https, native ad update * Update the ad server protocol module * Adding referrer * Improve Digital support for video * Improve Digital adapter: video * adapter version -> 6.0.0 --- modules/improvedigitalBidAdapter.js | 14 +++- .../modules/improvedigitalBidAdapter_spec.js | 82 +++++++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 61074985597..4ee2226395b 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -1,15 +1,15 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { config } from '../src/config'; -import { BANNER, NATIVE } from '../src/mediaTypes'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '5.3.0', + version: '6.0.0', code: BIDDER_CODE, aliases: ['id'], - supportedMediaTypes: [BANNER, NATIVE], + supportedMediaTypes: [BANNER, NATIVE, VIDEO], /** * Determines whether or not the given bid request is valid. @@ -87,6 +87,9 @@ export const spec = { bid.native.impressionTrackers.unshift(bidObject.nurl); } bid.mediaType = NATIVE; + } else if (bidObject.ad_type && bidObject.ad_type === 'video') { + bid.vastXml = bidObject.adm; + bid.mediaType = VIDEO; } else { // Banner let nurl = ''; @@ -186,6 +189,11 @@ function getNormalizedBidRequest(bid) { const bidFloorCur = utils.getBidIdParameter('bidFloorCur', bid.params); let normalizedBidRequest = {}; + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (bid.mediaType === 'video' || (videoMediaType && context !== 'outstream')) { + normalizedBidRequest.adTypes = [ VIDEO ]; + } if (placementId) { normalizedBidRequest.placementId = placementId; } else { diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 2bff6fba5bc..2d9d51c0d68 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -193,6 +193,38 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.referrer).to.equal('https://blah.com/test.html'); }); + it('should add ad type for instream video', function () { + let bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaType = 'video'; + let request = spec.buildRequests([bidRequest])[0]; + let params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']); + + bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaTypes = { + video: { + context: 'instream', + playerSize: [640, 480] + } + }; + request = spec.buildRequests([bidRequest])[0]; + params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']); + }); + + it('should not set ad type for outstream video', function() { + const bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }; + const request = spec.buildRequests([bidRequest])[0]; + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].ad_types).to.not.exist; + }); + it('should add schain', function () { const schain = '{"ver":"1.0","complete":1,"nodes":[{"asi":"headerlift.com","sid":"xyz","hp":1}]}'; const bidRequest = Object.assign({}, simpleBidRequest); @@ -456,6 +488,34 @@ describe('Improve Digital Adapter Tests', function () { } }; + const serverResponseVideo = { + 'body': { + 'id': '687a06c541d8d1', + 'site_id': 191642, + 'bid': [ + { + 'isNet': false, + 'id': '33e9500b21129f', + 'advid': '5279', + 'price': 1.45888594164456, + 'nurl': 'http://ice.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'h': 290, + 'pid': 1053688, + 'sync': [ + 'http://link1', + 'http://link2' + ], + 'crid': '422031', + 'w': 600, + 'cid': '99006', + 'adm': '', + 'ad_type': 'video' + } + ], + 'debug': '' + } + }; + const nativeEventtrackers = [ { event: 1, @@ -552,6 +612,22 @@ describe('Improve Digital Adapter Tests', function () { } ]; + let expectedBidVideo = [ + { + 'vastXml': '', + 'adId': '33e9500b21129f', + 'creativeId': '422031', + 'cpm': 1.45888594164456, + 'currency': 'USD', + 'height': 290, + 'mediaType': 'video', + 'netRevenue': false, + 'requestId': '33e9500b21129f', + 'ttl': 300, + 'width': 600 + } + ]; + it('should return a well-formed bid', function () { const bids = spec.interpretResponse(serverResponse); expect(bids).to.deep.equal(expectedBid); @@ -667,6 +743,12 @@ describe('Improve Digital Adapter Tests', function () { delete bids[0].ortbNative; expect(bids).to.deep.equal(expectedBids); }); + + // Video + it('should return a well-formed video bid', function () { + const bids = spec.interpretResponse(serverResponseVideo); + expect(bids).to.deep.equal(expectedBidVideo); + }); }); describe('getUserSyncs', function () { From 6ab0ade85244c37bdb3dcc18282d39fce56ea249 Mon Sep 17 00:00:00 2001 From: Salomon Rada Date: Wed, 16 Oct 2019 19:04:57 +0300 Subject: [PATCH 312/436] Gamoshi: Update aliases list. Add support for userSync. (#4319) * Add support for multi-format ad units. Add favoredMediaType property to params. * Add tests for gdpr consent. * Add adId to outbids * Modify media type resolving * Refactor multi-format ad units handler. * Modify the way of sending GDPR data. Update aliases. * Add new consent fields. Add unit test. * Add new consent fields. Add unit test. * Add support for id5 and unified id cookie sync. * Add support for id5 and unified id cookie sync. * Add restricted check for gdpr consent. --- modules/gamoshiBidAdapter.js | 58 ++++++++++++++++----- test/spec/modules/gamoshiBidAdapter_spec.js | 38 +++++++++++++- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index ec146b77c70..b18188cf33a 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -42,17 +42,16 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia', 'viewdeos', '9MediaOnline'], + aliases: ['gambid', 'cleanmedia', '9MediaOnline'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!bid.params.supplyPartnerId && - typeof bid.params.supplyPartnerId === 'string' && - (typeof bid.params['rtbEndpoint'] === 'undefined' || typeof bid.params['rtbEndpoint'] === 'string') && - (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && - (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number') && - (typeof bid.params['protocols'] === 'undefined' || Array.isArray(bid.params['protocols'])) && - (typeof bid.params.instl === 'undefined' || bid.params.instl === 0 || bid.params.instl === 1); + return !!bid.params.supplyPartnerId && utils.isStr(bid.params.supplyPartnerId) && + (!bid.params['rtbEndpoint'] || utils.isStr(bid.params['rtbEndpoint'])) && + (!bid.params.bidfloor || utils.isNumber(bid.params.bidfloor)) && + (!bid.params['adpos'] || utils.isNumber(bid.params['adpos'])) && + (!bid.params['protocols'] || Array.isArray(bid.params['protocols'])) && + (!bid.params.instl || bid.params.instl === 0 || bid.params.instl === 1); }, buildRequests: function (validBidRequests, bidderRequest) { @@ -75,16 +74,24 @@ export const spec = { 'imp': [], 'ext': {} }; + const gdprConsent = bidderRequest.gdprConsent; - if (bidderRequest.gdprConsent && - bidderRequest.gdprConsent.consentString && - bidderRequest.gdprConsent.gdprApplies) { + if (gdprConsent && gdprConsent.consentString && gdprConsent.gdprApplies) { rtbBidRequest.ext.gdpr_consent = { - consent_string: bidderRequest.gdprConsent.consentString, - consent_required: bidderRequest.gdprConsent.gdprApplies + consent_string: gdprConsent.consentString, + consent_required: gdprConsent.gdprApplies }; + rtbBidRequest.regs = { + ext: { + gdpr: gdprConsent.gdprApplies === true ? 1 : 0 + } + }; + rtbBidRequest.user = { + ext: { + consent: gdprConsent.consentString + } + } } - const imp = { 'id': transactionId, 'instl': params.instl === 1 ? 1 : 0, @@ -129,6 +136,15 @@ export const spec = { } } + let eids = []; + if (bidRequest && bidRequest.userId) { + addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id`), 'id5-sync.com', 'ID5ID'); + addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.tdid`), 'adserver.org', 'TDID'); + } + if (eids.length > 0) { + rtbBidRequest.user.ext.eids = eids; + } + if (rtbBidRequest.imp.length === 0) { return; } @@ -243,4 +259,18 @@ function renderOutstream(bid) { }); } +function addExternalUserId(eids, value, source, rtiPartner) { + if (utils.isStr(value)) { + eids.push({ + source, + uids: [{ + id: value, + ext: { + rtiPartner + } + }] + }); + } +} + registerBidder(spec); diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index a2c4eebc213..2d63d47a73e 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -227,13 +227,49 @@ describe('GamoshiAdapter', function () { it('builds request with gdpr consent', function () { let response = spec.buildRequests([bidRequest], bidRequest)[0]; + expect(response.data.ext.gdpr_consent).to.exist; expect(response.data.ext).to.have.property('gdpr_consent'); expect(response.data.ext.gdpr_consent.consent_string).to.equal('some string'); expect(response.data.ext.gdpr_consent.consent_required).to.equal(true); + + expect(response.data.regs.ext.gdpr).to.exist; + expect(response.data.user.ext.consent).to.equal('some string'); + }); + + it('build request with ID5 Id', function () { + const bidRequestClone = utils.deepClone(bidRequest); + bidRequestClone.userId = {}; + bidRequestClone.userId.id5id = 'id5-user-id'; + let request = spec.buildRequests([bidRequestClone], bidRequestClone)[0]; + expect(request.data.user.ext.eids).to.deep.equal([{ + 'source': 'id5-sync.com', + 'uids': [{ + 'id': 'id5-user-id', + 'ext': { + 'rtiPartner': 'ID5ID' + } + }] + }]); + }); + + it('build request with unified Id', function () { + const bidRequestClone = utils.deepClone(bidRequest); + bidRequestClone.userId = {}; + bidRequestClone.userId.tdid = 'tdid-user-id'; + let request = spec.buildRequests([bidRequestClone], bidRequestClone)[0]; + expect(request.data.user.ext.eids).to.deep.equal([{ + 'source': 'adserver.org', + 'uids': [{ + 'id': 'tdid-user-id', + 'ext': { + 'rtiPartner': 'TDID' + } + }] + }]); }); }); - describe('interpretResponse', function () { + describe('interpretResponse', () => { const bannerBidRequest = { 'adUnitCode': 'adunit-code', 'auctionId': '1d1a030790a475', From 8d9bcfd4109a4c9b41b6ce0b76f99ae4d1d84eea Mon Sep 17 00:00:00 2001 From: Neelanjan Sen <14229985+Fawke@users.noreply.github.com> Date: Thu, 17 Oct 2019 21:56:06 +0530 Subject: [PATCH 313/436] fix for userSync endpoint getting called with bidder alias names, instead of actual bidder names (#4265) --- modules/prebidServerBidAdapter/index.js | 9 +- .../modules/prebidServerBidAdapter_spec.js | 171 +++++++++++++----- 2 files changed, 134 insertions(+), 46 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 872e0bb81d9..93b8dc085f8 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -1,7 +1,6 @@ import Adapter from '../../src/adapter'; import { createBid } from '../../src/bidfactory'; import * as utils from '../../src/utils'; -import { ajax } from '../../src/ajax'; import { STATUS, S2S, EVENTS } from '../../src/constants'; import adapterManager from '../../src/adapterManager'; import { config } from '../../src/config'; @@ -11,6 +10,7 @@ import { isValid } from '../../src/adapters/bidderFactory'; import events from '../../src/events'; import includes from 'core-js/library/fn/array/includes'; import { S2S_VENDORS } from './config.js'; +import { ajax } from '../../src/ajax'; const getConfig = config.getConfig; @@ -148,7 +148,6 @@ function queueSync(bidderCodes, gdprConsent) { } } const jsonPayload = JSON.stringify(payload); - ajax(_s2sConfig.syncEndpoint, (response) => { try { @@ -960,7 +959,11 @@ export function PrebidServer() { if (_s2sConfig && _s2sConfig.syncEndpoint) { let consent = (Array.isArray(bidRequests) && bidRequests.length > 0) ? bidRequests[0].gdprConsent : undefined; - queueSync(_s2sConfig.bidders, consent); + let syncBidders = _s2sConfig.bidders + .map(bidder => adapterManager.aliasRegistry[bidder] || bidder) + .filter((bidder, index, array) => (array.indexOf(bidder) === index)); + + queueSync(syncBidders, consent); } const request = protocolAdapter().buildRequest(s2sBidRequest, bidRequests, validAdUnits); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 658f130d144..7945be68282 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -2,10 +2,8 @@ import { expect } from 'chai'; import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter/index.js'; import adapterManager from 'src/adapterManager'; import * as utils from 'src/utils'; -import { userSync } from 'src/userSync'; import { ajax } from 'src/ajax'; import { config } from 'src/config'; -import { requestBidsHook } from 'modules/consentManagement'; import events from 'src/events'; import CONSTANTS from 'src/constants'; @@ -32,7 +30,7 @@ const REQUEST = { 'sizes': [[300, 250], [300, 600]], 'mediaTypes': { 'banner': { - 'sizes': [[ 300, 250 ], [ 300, 300 ]] + 'sizes': [[300, 250], [300, 300]] }, 'native': { 'title': { @@ -77,7 +75,7 @@ const VIDEO_REQUEST = { 'sizes': [640, 480], 'mediaTypes': { 'video': { - 'playerSize': [[ 640, 480 ]], + 'playerSize': [[640, 480]], 'mimes': ['video/mp4'] } }, @@ -107,7 +105,7 @@ const OUTSTREAM_VIDEO_REQUEST = { 'sizes': [640, 480], 'mediaTypes': { 'video': { - playerSize: [[ 640, 480 ]], + playerSize: [[640, 480]], context: 'outstream', mimes: ['video/mp4'] }, @@ -325,7 +323,7 @@ const RESPONSE_OPENRTB = { 'price': 0.5, 'adm': '', 'adid': '29681110', - 'adomain': [ 'appnexus.com' ], + 'adomain': ['appnexus.com'], 'iurl': 'http://lax1-ib.adnxs.com/cr?id=2968111', 'cid': '958', 'crid': '2968111', @@ -517,6 +515,11 @@ describe('S2S Adapter', function () { }, 'bid_id': '123', 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', 'sizes': [300, 250], 'bidId': '123', @@ -553,11 +556,11 @@ describe('S2S Adapter', function () { xhr.restore(); }); - it('should not add outstrean without renderer', function() { + it('should not add outstrean without renderer', function () { let ortb2Config = utils.deepClone(CONFIG); ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' - config.setConfig({s2sConfig: ortb2Config}); + config.setConfig({ s2sConfig: ortb2Config }); adapter.callBids(OUTSTREAM_VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); @@ -570,7 +573,7 @@ describe('S2S Adapter', function () { }); it('exists converts types', function () { - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid).to.have.property('cache_markup', 2); @@ -604,7 +607,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.consent).is.equal('abc123'); config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); requestBid = JSON.parse(requests[1].requestBody); @@ -681,7 +684,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { cacheMarkup: 999 }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid).to.have.property('cache_markup', 0); @@ -722,7 +725,8 @@ describe('S2S Adapter', function () { }); it('adds device and app objects to request', function () { - const _config = { s2sConfig: CONFIG, + const _config = { + s2sConfig: CONFIG, device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, app: { bundle: 'com.test.app' }, }; @@ -737,7 +741,7 @@ describe('S2S Adapter', function () { }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -762,7 +766,7 @@ describe('S2S Adapter', function () { }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -785,7 +789,7 @@ describe('S2S Adapter', function () { }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -858,7 +862,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const aliasBidder = { bidder: 'brealtime', @@ -889,7 +893,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const alias = 'foobar'; const aliasBidder = { @@ -923,7 +927,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const myRequest = utils.deepClone(REQUEST); myRequest.ad_units[0].bids[0].params.usePaymentRule = true; @@ -949,7 +953,7 @@ describe('S2S Adapter', function () { config.resetConfig(); const oldS2sConfig = Object.assign({}, CONFIG); - config.setConfig({s2sConfig: oldS2sConfig}); + config.setConfig({ s2sConfig: oldS2sConfig }); const myRequest2 = utils.deepClone(REQUEST); myRequest2.ad_units[0].bids[0].params.keywords = { @@ -1068,7 +1072,7 @@ describe('S2S Adapter', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; config.setConfig({ - currency: {adServerCurrency: ['USD', 'GB', 'UK', 'AU']}, + currency: { adServerCurrency: ['USD', 'GB', 'UK', 'AU'] }, s2sConfig: s2sConfig }); @@ -1083,7 +1087,7 @@ describe('S2S Adapter', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; config.setConfig({ - currency: {adServerCurrency: 'NZ'}, + currency: { adServerCurrency: 'NZ' }, s2sConfig: s2sConfig }); @@ -1097,7 +1101,7 @@ describe('S2S Adapter', function () { it('when config \'currency.adServerCurrency\' is unset: ORTB should not define a \'cur\' property', function () { let s2sConfig = utils.deepClone(CONFIG); s2sConfig.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'; - config.setConfig({s2sConfig: s2sConfig}); + config.setConfig({ s2sConfig: s2sConfig }); const bidRequests = utils.deepClone(BID_REQUESTS); adapter.callBids(REQUEST, bidRequests, addBidResponse, done, ajax); @@ -1246,7 +1250,7 @@ describe('S2S Adapter', function () { }); }); - it('passes schain object in request', function() { + it('passes schain object in request', function () { const bidRequests = utils.deepClone(BID_REQUESTS); const schainObject = { 'ver': '1.0', @@ -1298,7 +1302,7 @@ describe('S2S Adapter', function () { it('registers bids and calls BIDDER_DONE', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); @@ -1321,7 +1325,7 @@ describe('S2S Adapter', function () { it('registers video bids', function () { server.respondWith(JSON.stringify(VIDEO_RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); @@ -1339,7 +1343,7 @@ describe('S2S Adapter', function () { it('does not call addBidResponse and calls done when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1350,7 +1354,7 @@ describe('S2S Adapter', function () { it('does not call addBidResponse and calls done when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_COOKIE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1361,7 +1365,7 @@ describe('S2S Adapter', function () { it('does not call addBidResponse and calls done when ad unit is set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_UNIT_SET)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1372,7 +1376,7 @@ describe('S2S Adapter', function () { it('registers successful bids and calls done when there are less bids than requests', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1390,7 +1394,7 @@ describe('S2S Adapter', function () { it('should have dealId in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); const response = addBidResponse.firstCall.args[1]; @@ -1400,11 +1404,11 @@ describe('S2S Adapter', function () { it('should pass through default adserverTargeting if present in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); const response = addBidResponse.firstCall.args[1]; - expect(response).to.have.property('adserverTargeting').that.deep.equals({'foo': 'bar'}); + expect(response).to.have.property('adserverTargeting').that.deep.equals({ 'foo': 'bar' }); }); it('registers client user syncs when client bid adapter is present', function () { @@ -1415,7 +1419,7 @@ describe('S2S Adapter', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1433,7 +1437,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB)); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1447,7 +1451,7 @@ describe('S2S Adapter', function () { it('registers bid responses when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); @@ -1467,7 +1471,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB)); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1490,7 +1494,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB_VIDEO)); adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1510,7 +1514,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); cacheResponse.seatbid.forEach(item => { item.bid[0].ext.prebid.cache = { @@ -1536,7 +1540,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); const targetingTestData = { hb_cache_path: '/cache', @@ -1564,7 +1568,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const cacheResponse = utils.deepClone(RESPONSE_OPENRTB_VIDEO); cacheResponse.seatbid.forEach(item => { item.bid[0].ext.prebid.targeting = { @@ -1594,7 +1598,7 @@ describe('S2S Adapter', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); server.respondWith(JSON.stringify(RESPONSE_OPENRTB_NATIVE)); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -1624,7 +1628,7 @@ describe('S2S Adapter', function () { } config.setConfig(_config); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); @@ -1633,13 +1637,20 @@ describe('S2S Adapter', function () { }); describe('s2sConfig', function () { + let xhr; + let requests; let logErrorSpy; beforeEach(function () { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); logErrorSpy = sinon.spy(utils, 'logError'); + resetSyncedStatus(); }); afterEach(function () { + xhr.restore(); utils.logError.restore(); }); @@ -1792,11 +1803,85 @@ describe('S2S Adapter', function () { config.setConfig({ s2sConfig: { syncUrlModifier: { - appnexus: () => {} + appnexus: () => { } } } }); expect(typeof config.getConfig('s2sConfig').syncUrlModifier.appnexus).to.equal('function') }); + + it('should set correct bidder names to bidders property when using an alias for that bidder', function () { + const s2sConfig = utils.deepClone(CONFIG); + + // Add syncEndpoint so that the request goes to the User Sync endpoint + // Modify the bidders property to include an alias for Rubicon adapter + s2sConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + s2sConfig.bidders = ['appnexus', 'rubicon-alias']; + + const request = utils.deepClone(REQUEST); + + // Add another bidder, `rubicon-alias` + request.ad_units[0].bids.push({ + bidder: 'rubicon-alias', + params: { + accoundId: 14062, + siteId: 70608, + zoneId: 498816 + } + }); + + // create an alias for the Rubicon Bid Adapter + adapterManager.aliasBidAdapter('rubicon', 'rubicon-alias'); + + config.setConfig({ s2sConfig }); + + const bidRequest = utils.deepClone(BID_REQUESTS); + bidRequest.push({ + 'bidderCode': 'rubicon-alias', + 'auctionId': '4146ab2b-9422-4040-9b1c-966fffbfe2d4', + 'bidderRequestId': '4b1a4f9c3e4546', + 'tid': 'd7fa8342-ae22-4ca1-b237-331169350f84', + 'bids': [ + { + 'bidder': 'rubicon-alias', + 'params': { + 'accountId': 14062, + 'siteId': 70608, + 'zoneId': 498816 + }, + 'bid_id': '2a9523915411c3', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ + 300, + 250 + ] + ] + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '78ddc106-b7d8-45d1-bd29-86993098e53d', + 'sizes': [ + [ + 300, + 250 + ] + ], + 'bidId': '2a9523915411c3', + 'bidderRequestId': '4b1a4f9c3e4546', + 'auctionId': '4146ab2b-9422-4040-9b1c-966fffbfe2d4' + } + ], + 'auctionStart': 1569234122602, + 'timeout': 1000, + 'src': 's2s' + }); + + adapter.callBids(request, bidRequest, addBidResponse, done, ajax); + + const requestBid = JSON.parse(requests[0].requestBody); + expect(requestBid.bidders).to.deep.equal(['appnexus', 'rubicon']); + }); }); }); From 171c5a2c5241dedacdf0616bc17d77705da24fe7 Mon Sep 17 00:00:00 2001 From: Index Exchange 3 Prebid Team Date: Thu, 17 Oct 2019 13:11:20 -0400 Subject: [PATCH 314/436] modify ixBidAdapater to always use the secure endpoint (#4323) --- modules/ixBidAdapter.js | 10 +--------- test/spec/modules/ixBidAdapter_spec.js | 3 +-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 8d76d862655..85d3be2f0ec 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -6,7 +6,6 @@ import { registerBidder } from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'ix'; const BANNER_SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; -const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus'; const SUPPORTED_AD_TYPES = [BANNER]; const ENDPOINT_VERSION = 7.2; const CENT_TO_DOLLAR_FACTOR = 100; @@ -188,10 +187,7 @@ export const spec = { let validBidRequest = null; let bannerImp = null; - // Always start by assuming the protocol is HTTPS. This way, it will work - // whether the page protocol is HTTP or HTTPS. Then check if the page is - // actually HTTP.If we can guarantee it is, then, and only then, set protocol to - // HTTP. + // Always use secure HTTPS protocol. let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { @@ -258,10 +254,6 @@ export const spec = { if (options.refererInfo) { r.site.page = options.refererInfo.referer; - - if (options.refererInfo.referer && options.refererInfo.referer.indexOf('https') !== 0) { - baseUrl = BANNER_INSECURE_BID_URL; - } } } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 38e64e8d338..120d02408d7 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -5,7 +5,6 @@ import { newBidder } from 'src/adapters/bidderFactory'; import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { - const IX_INSECURE_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; const BIDDER_VERSION = 7.2; @@ -401,7 +400,7 @@ describe('IndexexchangeAdapter', function () { it('request should be made to IX endpoint with GET method', function () { expect(requestMethod).to.equal('GET'); - expect(requestUrl).to.equal(IX_INSECURE_ENDPOINT); + expect(requestUrl).to.equal(IX_SECURE_ENDPOINT); }); it('query object (version, siteID and request) should be correct', function () { From fb2bc787c3bad60236b9628a38b7940c59a89e0d Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Thu, 17 Oct 2019 10:33:52 -0700 Subject: [PATCH 315/436] PubMatic to support Parrable User Id sub-module (#4324) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * PubMatic to support parrable id --- modules/pubmaticBidAdapter.js | 1 + test/spec/modules/pubmaticBidAdapter_spec.js | 36 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 58d8d773dae..59f0f7a7db8 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -651,6 +651,7 @@ function _handleEids(payload, validBidRequests) { _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.criteortus.${BIDDER_CODE}.userid`), 'criteortus', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.idl_env`), 'liveramp.com', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.lipb.lipbid`), 'liveintent.com', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.parrableid`), 'parrable.com', 1); } if (eids.length > 0) { payload.user.eids = eids; diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 22c0f840026..32fdd774518 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1696,6 +1696,42 @@ describe('PubMatic adapter', function () { expect(data.user.eids).to.equal(undefined); }); }); + + describe('Parrable Id', function() { + it('send the Parrable id if it is present', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.parrableid = 'parrable-user-id'; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.deep.equal([{ + 'source': 'parrable.com', + 'uids': [{ + 'id': 'parrable-user-id', + 'atype': 1 + }] + }]); + }); + + it('do not pass if not string', function() { + bidRequests[0].userId = {}; + bidRequests[0].userId.parrableid = 1; + let request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.parrableid = []; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.parrableid = null; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + bidRequests[0].userId.parrableid = {}; + request = spec.buildRequests(bidRequests, {}); + data = JSON.parse(request.data); + expect(data.user.eids).to.equal(undefined); + }); + }); }); it('Request params check for video ad', function () { From b41a7161d1853bb28546db7168518de8a859a848 Mon Sep 17 00:00:00 2001 From: Michael Kuryshev Date: Fri, 18 Oct 2019 21:45:30 +0200 Subject: [PATCH 316/436] VISX: currency validation & fix double escape of referer (#4299) --- modules/visxBidAdapter.js | 83 ++++++++++++++---------- test/spec/modules/visxBidAdapter_spec.js | 52 ++++++++------- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 2f9ec73c569..15334e46e31 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -15,8 +15,11 @@ const LOG_ERROR_MESS = { emptySeatbid: 'Seatbid array from response has an empty item', emptyResponse: 'Response is empty', hasEmptySeatbidArray: 'Response has empty seatbid array', - hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ' + hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - ', + notAllowedCurrency: 'Currency is not supported - ', + currencyMismatch: 'Currency from the request is not match currency from the response - ' }; +const currencyWhiteList = ['EUR', 'USD', 'GBP', 'PLN']; export const spec = { code: BIDDER_CODE, isBidRequestValid: function(bid) { @@ -34,6 +37,11 @@ export const spec = { DEFAULT_CUR; let reqId; + if (currencyWhiteList.indexOf(currency) === -1) { + utils.logError(LOG_ERROR_MESS.notAllowedCurrency + currency); + return; + } + bids.forEach(bid => { reqId = bid.bidderRequestId; const {params: {uid}, adUnitCode} = bid; @@ -78,7 +86,7 @@ export const spec = { if (bidderRequest) { if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { - payload.u = encodeURIComponent(bidderRequest.refererInfo.referer); + payload.u = bidderRequest.refererInfo.referer; } if (bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.consentString) { @@ -158,43 +166,48 @@ function _addBidResponse(serverBid, bidsMap, currency, bidResponses, bidsWithout if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else { + const reqCurrency = currency || DEFAULT_CUR; const awaitingBids = bidsMap[serverBid.auid]; if (awaitingBids) { - const sizeId = bidsWithoutSizeMatching ? `${serverBid.w}x${serverBid.h}` : Object.keys(awaitingBids)[0]; - if (awaitingBids[sizeId]) { - const slot = awaitingBids[sizeId][0]; - - const bid = slot.bids.shift(); - bidResponses.push({ - requestId: bid.bidId, - bidderCode: spec.code, - cpm: serverBid.price, - width: serverBid.w, - height: serverBid.h, - creativeId: serverBid.auid, - currency: currency || DEFAULT_CUR, - netRevenue: true, - ttl: TIME_TO_LIVE, - ad: serverBid.adm, - dealId: serverBid.dealid - }); - - if (!slot.bids.length) { - slot.parents.forEach(({parent, key, uid}) => { - const index = parent[key].indexOf(slot); - if (index > -1) { - parent[key].splice(index, 1); - } - if (!parent[key].length) { - delete parent[key]; - if (!utils.getKeys(parent).length) { - delete bidsMap[uid]; - } - } + if (serverBid.cur && serverBid.cur !== reqCurrency) { + errorMessage = LOG_ERROR_MESS.currencyMismatch + reqCurrency + ' - ' + serverBid.cur; + } else { + const sizeId = bidsWithoutSizeMatching ? `${serverBid.w}x${serverBid.h}` : Object.keys(awaitingBids)[0]; + if (awaitingBids[sizeId]) { + const slot = awaitingBids[sizeId][0]; + + const bid = slot.bids.shift(); + bidResponses.push({ + requestId: bid.bidId, + bidderCode: spec.code, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, + currency: reqCurrency, + netRevenue: true, + ttl: TIME_TO_LIVE, + ad: serverBid.adm, + dealId: serverBid.dealid }); + + if (!slot.bids.length) { + slot.parents.forEach(({parent, key, uid}) => { + const index = parent[key].indexOf(slot); + if (index > -1) { + parent[key].splice(index, 1); + } + if (!parent[key].length) { + delete parent[key]; + if (!utils.getKeys(parent).length) { + delete bidsMap[uid]; + } + } + }); + } + } else { + bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); } - } else { - bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 09ce92479f9..167d54e37a6 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -45,7 +45,7 @@ describe('VisxAdapter', function () { referer: 'http://example.com' } }; - const encodedReferrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; let bidRequests = [ { 'bidder': 'visx', @@ -86,7 +86,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535'); expect(payload).to.have.property('sizes', '300x250,300x600'); @@ -98,7 +98,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -111,7 +111,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -124,7 +124,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -138,7 +138,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -149,16 +149,16 @@ describe('VisxAdapter', function () { it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( - arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); + arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'GBP' : 'USD'); const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'JPY'); + expect(payload).to.have.property('cur', 'GBP'); getConfigStub.restore(); }); @@ -168,7 +168,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', encodedReferrer); + expect(payload).to.have.property('u', referrer); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); @@ -204,11 +204,11 @@ describe('VisxAdapter', function () { describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'price': 0, 'auid': 903537, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0, 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, {'seat': '1'}, @@ -346,7 +346,7 @@ describe('VisxAdapter', function () { 'auctionId': '1cbd2feafe5e8b', } ]; - const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); + const getConfigStub = sinon.stub(config, 'getConfig').returns('PLN'); const request = spec.buildRequests(bidRequests); const expectedResponse = [ { @@ -358,13 +358,15 @@ describe('VisxAdapter', function () { 'height': 250, 'ad': '
test content 1
', 'bidderCode': 'visx', - 'currency': 'JPY', + 'currency': 'PLN', 'netRevenue': true, 'ttl': 360, } ]; - const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + const response = Object.assign({}, responses[0]); + Object.assign(response.bid[0], {'cur': 'PLN'}); + const result = spec.interpretResponse({'body': {'seatbid': [response]}}, request); expect(result).to.deep.equal(expectedResponse); getConfigStub.restore(); }); @@ -412,11 +414,11 @@ describe('VisxAdapter', function () { it('complicated case', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
test content 4
', 'auid': 903535, 'h': 600, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 5
', 'auid': 903536, 'h': 600, 'w': 350}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'adm': '
test content 4
', 'auid': 903535, 'h': 600, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 5
', 'auid': 903536, 'h': 600, 'w': 350, 'cur': 'EUR'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -550,8 +552,8 @@ describe('VisxAdapter', function () { it('dublicate uids and sizes in one slot', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, ]; const bidRequests = [ { From 78b6ca3364719ecbd0c944fab94c7700aef1688a Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Sun, 20 Oct 2019 18:29:18 -0700 Subject: [PATCH 317/436] PubMatic to support coppa (#4336) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * added coppa compliance --- modules/pubmaticBidAdapter.js | 10 +++++ test/spec/modules/pubmaticBidAdapter_spec.js | 40 ++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 59f0f7a7db8..51cebebf6e4 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -920,6 +920,11 @@ export const spec = { }; } + // coppa compliance + if (config.getConfig('coppa') === true) { + utils.deepSetValue(payload, 'regs.coppa', 1); + } + _handleDealCustomTargetings(payload, dctrArr, validBidRequests); _handleEids(payload, validBidRequests); _blockedIabCategoriesValidation(payload, blockedIabCategories); @@ -1019,6 +1024,11 @@ export const spec = { syncurl += '&gdpr_consent=' + encodeURIComponent(gdprConsent.consentString || ''); } + // coppa compliance + if (config.getConfig('coppa') === true) { + syncurl += '&coppa=1'; + } + if (syncOptions.iframeEnabled) { return [{ type: 'iframe', diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 32fdd774518..feb64dfe4ac 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1171,6 +1171,46 @@ describe('PubMatic adapter', function () { // should have called DigiTrust.getUser() once expect(window.DigiTrust.getUser.calledOnce).to.equal(true); }); + + it('should NOT include coppa flag in bid request if coppa config is not present', () => { + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + if (data.regs) { + // in case GDPR is set then data.regs will exist + expect(data.regs.coppa).to.equal(undefined); + } else { + expect(data.regs).to.equal(undefined); + } + }); + + it('should include coppa flag in bid request if coppa is set to true', () => { + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': true + }; + return config[key]; + }); + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.regs.coppa).to.equal(1); + }); + + it('should NOT include coppa flag in bid request if coppa is set to false', () => { + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': false + }; + return config[key]; + }); + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + if (data.regs) { + // in case GDPR is set then data.regs will exist + expect(data.regs.coppa).to.equal(undefined); + } else { + expect(data.regs).to.equal(undefined); + } + }); }); describe('AdsrvrOrgId from config', function() { From 33b68904c53a95637d56107b010da75148bb3ecc Mon Sep 17 00:00:00 2001 From: Roffray Date: Mon, 21 Oct 2019 03:40:16 +0200 Subject: [PATCH 318/436] vuble: outstream has fullscreen option (#4320) * Mod: vuble oustream has fullscreen option * Add: vuble test for outstream scenario --- modules/vubleBidAdapter.js | 2 +- test/spec/modules/vubleBidAdapter_spec.js | 52 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/modules/vubleBidAdapter.js b/modules/vubleBidAdapter.js index 80d62d21842..63f817358de 100644 --- a/modules/vubleBidAdapter.js +++ b/modules/vubleBidAdapter.js @@ -23,7 +23,7 @@ const outstreamRender = bid => { showBigPlayButton: false, showProgressBar: 'bar', showVolume: false, - allowFullscreen: false, + allowFullscreen: true, skippable: false, } }); diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 8996c1b4957..b38ad8f8584 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -280,4 +280,56 @@ describe('VubleAdapter', function () { expect(adapter.getUserSyncs(syncOptions, [response])).to.deep.equal([result]); }) }); + + describe('Check outstream scenario with renderer', function () { + // bid Request + let bid = { + data: { + context: 'outstream', + env: 'net', + width: '640', + height: '360', + pub_id: '3', + zone_id: '12345', + bid_id: 'abdc', + floor_price: 5.50, // optional + adUnitCode: 'code' + }, + method: 'POST', + url: '//player.mediabong.net/prebid/request' + }; + // Server's response + let response = { + body: { + status: 'ok', + cpm: 5.00, + creativeId: '2468', + url: 'https//player.mediabong.net/prebid/ad/a1b2c3d4', + dealId: 'MDB-TEST-1357', + renderer_id: 0, + renderer_url: 'vuble_renderer.js', + content: 'test' + } + }; + + let adResponse = { + ad: { + video: { + content: 'test' + } + } + }; + let adUnitCode = 'code'; + let rendererUrl = 'vuble_renderer.js'; + let rendererId = 0; + + let formattedResponses = adapter.interpretResponse(response, bid); + it('should equal to the expected format result', function () { + expect(formattedResponses[0].adResponse).to.deep.equal(adResponse); + expect(formattedResponses[0].adUnitCode).to.deep.equal(adUnitCode); + expect(formattedResponses[0].renderer.url).to.equal(rendererUrl); + expect(formattedResponses[0].renderer.id).to.equal(rendererId); + expect(formattedResponses[0].renderer.render).to.exist.and.to.be.a('function'); + }); + }); }); From 5ac7f00f1dc24c543c13df5355dd739f5920b7aa Mon Sep 17 00:00:00 2001 From: Dan Bogdan <43830380+EMXDigital@users.noreply.github.com> Date: Mon, 21 Oct 2019 09:06:52 -0400 Subject: [PATCH 319/436] EMXDigital: hotfix to resolve URIError from decodeURIComponent (#4333) * hotfix to resolve URIError from decodeURIComponent * added unit for decoding adm --- modules/emx_digitalBidAdapter.js | 4 ++-- test/spec/modules/emx_digitalBidAdapter_spec.js | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/emx_digitalBidAdapter.js b/modules/emx_digitalBidAdapter.js index 12f3482184b..7167f9018aa 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/emx_digitalBidAdapter.js @@ -7,7 +7,7 @@ import includes from 'core-js/library/fn/array/includes'; const BIDDER_CODE = 'emx_digital'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = '//js.brealtime.com/outstream/1.30.0/bundle.js'; -const ADAPTER_VERSION = '1.41.0'; +const ADAPTER_VERSION = '1.41.1'; const DEFAULT_CUR = 'USD'; export const emxAdapter = { @@ -116,7 +116,7 @@ export const emxAdapter = { }, parseResponse: (bidResponseAdm) => { try { - return decodeURIComponent(bidResponseAdm); + return decodeURIComponent(bidResponseAdm.replace(/%(?![0-9][0-9a-fA-F]+)/g, '%25')); } catch (err) { utils.logError('emx_digitalBidAdapter', 'error', err); } diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/emx_digitalBidAdapter_spec.js index 16f17174f88..80fd12a237c 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/emx_digitalBidAdapter_spec.js @@ -527,6 +527,15 @@ describe('emx_digital Adapter', function () { }); expect(result.length).to.equal(0); }); + + it('should not throw an error when decoding an improperly encoded adm', function () { + serverResponse.seatbid[0].bid[0].adm = '\\<\\/script\\>'; + serverResponse.seatbid[1].bid[0].adm = '%3F%%3Demx%3C3prebid' + + assert.doesNotThrow(() => spec.interpretResponse({ + body: serverResponse + })); + }); }); describe('getUserSyncs', function () { From 98c95b0cd57f9a8a04ec669fbebe6b50a5362a7a Mon Sep 17 00:00:00 2001 From: rumesh Date: Mon, 21 Oct 2019 20:13:37 +0000 Subject: [PATCH 320/436] Specify second parameter for parseInt for pubmaticBidAdapter (#4347) --- modules/pubmaticBidAdapter.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 51cebebf6e4..73e6d8cfb52 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -174,8 +174,8 @@ function _parseAdSlot(bid) { utils.logWarn(LOG_WARN_PREFIX + 'AdSlot Error: adSlot not in required format'); return; } - bid.params.width = parseInt(splits[0]); - bid.params.height = parseInt(splits[1]); + bid.params.width = parseInt(splits[0], 10); + bid.params.height = parseInt(splits[1], 10); } else if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(BANNER) && bid.mediaTypes.banner.hasOwnProperty('sizes')) { @@ -441,8 +441,8 @@ function _createBannerRequest(bid) { utils.logWarn(LOG_WARN_PREFIX + 'Error: mediaTypes.banner.size missing for adunit: ' + bid.params.adUnit + '. Ignoring the banner impression in the adunit.'); return bannerObj; } else { - bannerObj.w = parseInt(sizes[0][0]); - bannerObj.h = parseInt(sizes[0][1]); + bannerObj.w = parseInt(sizes[0][0], 10); + bannerObj.h = parseInt(sizes[0][1], 10); sizes = sizes.splice(1, sizes.length - 1); } } else { @@ -482,11 +482,11 @@ function _createVideoRequest(bid) { } // read playersize and assign to h and w. if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { - videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0]); - videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1]); + videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0], 10); + videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1], 10); } else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) { - videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0]); - videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1]); + videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0], 10); + videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1], 10); } if (bid.params.video.hasOwnProperty('skippable')) { videoObj.ext = { From c8f74e09f6e2572da588a0296791a5c184dab7f4 Mon Sep 17 00:00:00 2001 From: oasis <2394426+bmwcmw@users.noreply.github.com> Date: Tue, 22 Oct 2019 11:42:04 +0200 Subject: [PATCH 321/436] Remove usage of getTopWindowUrl in Prebid Adapter (#4341) --- modules/criteoBidAdapter.js | 16 +++++--- test/spec/modules/criteoBidAdapter_spec.js | 45 +++++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 86f289421ce..7f292c76e20 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -8,7 +8,7 @@ import find from 'core-js/library/fn/array/find'; import JSEncrypt from 'jsencrypt/bin/jsencrypt'; import sha256 from 'crypto-js/sha256'; -export const ADAPTER_VERSION = 21; +export const ADAPTER_VERSION = 23; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; @@ -79,7 +79,7 @@ export const spec = { url = adapter.buildCdbUrl(); data = adapter.buildCdbRequest(); } else { - const context = buildContext(bidRequests); + const context = buildContext(bidRequests, bidderRequest); url = buildCdbUrl(context); data = buildCdbRequest(context, bidRequests, bidderRequest); } @@ -177,14 +177,18 @@ function publisherTagAvailable() { /** * @param {BidRequest[]} bidRequests + * @param bidderRequest * @return {CriteoContext} */ -function buildContext(bidRequests) { - const url = utils.getTopWindowUrl(); - const queryString = parse(url).search; +function buildContext(bidRequests, bidderRequest) { + let referrer = ''; + if (bidderRequest && bidderRequest.refererInfo) { + referrer = bidderRequest.refererInfo.referer; + } + const queryString = parse(referrer).search; const context = { - url: url, + url: referrer, debug: queryString['pbt_debug'] === '1', noLog: queryString['pbt_nolog'] === '1', amp: false, diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 03500d4add6..e5d789ff60d 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -368,7 +368,11 @@ describe('The Criteo bidding adapter', function () { }); describe('buildRequests', function () { + const refererUrl = 'https://criteo.com?pbt_debug=1&pbt_nolog=1'; const bidderRequest = { + refererInfo: { + referer: refererUrl + }, timeout: 3000, gdprConsent: { gdprApplies: 1, @@ -385,10 +389,23 @@ describe('The Criteo bidding adapter', function () { config.resetConfig(); }); - it('should properly build a zoneId request', function () { - const publisherUrl = 'https://criteo.com?pbt_debug=1&pbt_nolog=1'; - utilsMock.expects('getTopWindowUrl').withExactArgs().once().returns(publisherUrl); + it('should properly build a request if refererInfo is not provided', function () { + const bidderRequest = {}; + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: {} + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request.data; + expect(ortbRequest.publisher.url).to.equal(''); + }); + it('should properly build a zoneId request', function () { const bidRequests = [ { bidder: 'criteo', @@ -407,7 +424,7 @@ describe('The Criteo bidding adapter', function () { expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d+&im=1&debug=1&nolog=1/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.publisher.url).to.equal(publisherUrl); + expect(ortbRequest.publisher.url).to.equal(refererUrl); expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); @@ -421,6 +438,9 @@ describe('The Criteo bidding adapter', function () { it('should properly build a networkId request', function () { const bidderRequest = { + refererInfo: { + referer: refererUrl + }, timeout: 3000, gdprConsent: { gdprApplies: 0, @@ -451,7 +471,7 @@ describe('The Criteo bidding adapter', function () { expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.url).to.equal(refererUrl); expect(ortbRequest.publisher.networkid).to.equal(456); expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); @@ -465,7 +485,12 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a mixed request', function () { - const bidderRequest = { timeout: 3000 }; + const bidderRequest = { + refererInfo: { + referer: refererUrl + }, + timeout: 3000 + }; const bidRequests = [ { bidder: 'criteo', @@ -490,7 +515,7 @@ describe('The Criteo bidding adapter', function () { expect(request.url).to.match(/^https:\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; - expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.url).to.equal(refererUrl); expect(ortbRequest.publisher.networkid).to.equal(456); expect(ortbRequest.slots).to.have.lengthOf(2); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); @@ -517,9 +542,9 @@ describe('The Criteo bidding adapter', function () { }, }, ]; - const bidderRequest = { timeout: 3000, - gdprConsent: { - }, + const bidderRequest = { + timeout: 3000, + gdprConsent: {}, }; const ortbRequest = spec.buildRequests(bidRequests, bidderRequest).data; From cab0fd5a7a5c2231839241b525a66b5bd44979d8 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 22 Oct 2019 05:40:58 -0700 Subject: [PATCH 322/436] Conversant Bid Adapter update for 3.0 (#4284) --- modules/conversantBidAdapter.js | 13 +++--- modules/conversantBidAdapter.md | 6 ++- .../spec/modules/conversantBidAdapter_spec.js | 40 +++++++++---------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index 00ca6a7bbd6..a3479a9d1d1 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; import { BANNER, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'conversant'; -const URL = '//web.hb.ad.cpe.dotomi.com/s2s/header/24'; +const URL = 'https://web.hb.ad.cpe.dotomi.com/s2s/header/24'; export const spec = { code: BIDDER_CODE, @@ -44,26 +44,24 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {BidRequest[]} validBidRequests - an array of bids + * @param bidderRequest * @return {ServerRequest} Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { - const loc = utils.getTopWindowLocation(); - const page = loc.href; - const isPageSecure = (loc.protocol === 'https:') ? 1 : 0; + const page = (bidderRequest && bidderRequest.refererInfo) ? bidderRequest.refererInfo.referer : ''; let siteId = ''; let requestId = ''; let pubcid = null; const conversantImps = validBidRequests.map(function(bid) { const bidfloor = utils.getBidIdParameter('bidfloor', bid.params); - const secure = isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0); siteId = utils.getBidIdParameter('site_id', bid.params); requestId = bid.auctionId; const imp = { id: bid.bidId, - secure: secure, + secure: 1, bidfloor: bidfloor || 0, displaymanager: 'Prebid.js', displaymanagerver: '$prebid.version$' @@ -154,6 +152,7 @@ export const spec = { * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. + * @param bidRequest * @return {Bid[]} An array of bids which were nested inside the server. */ interpretResponse: function(serverResponse, bidRequest) { @@ -249,7 +248,7 @@ function getDevice() { * * [[300, 250], [300, 600]] => [{w: 300, h: 250}, {w: 300, h: 600}] * - * @param {number[2][]|number[2]} bidSizes - arrays of widths and heights + * @param {Array.>} bidSizes - arrays of widths and heights * @returns {object[]} Array of objects with w and h */ function convertSizes(bidSizes) { diff --git a/modules/conversantBidAdapter.md b/modules/conversantBidAdapter.md index 3ce83d8c893..5aba5653043 100644 --- a/modules/conversantBidAdapter.md +++ b/modules/conversantBidAdapter.md @@ -13,7 +13,11 @@ Module that connects to Conversant's demand sources. Supports banners and video var adUnits = [ { code: 'banner-test-div', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250],[300,600]] + } + }, bids: [{ bidder: "conversant", params: { diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index aeadc3bf828..6c9f0c8e6e5 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -2,8 +2,6 @@ import {expect} from 'chai'; import {spec} from 'modules/conversantBidAdapter'; import * as utils from 'src/utils'; -var Adapter = require('modules/conversantBidAdapter'); - describe('Conversant adapter tests', function() { const siteId = '108060'; const versionPattern = /^\d+\.\d+\.\d+(.)*$/; @@ -16,7 +14,6 @@ describe('Conversant adapter tests', function() { site_id: siteId, position: 1, tag_id: 'tagid-1', - secure: false, bidfloor: 0.5 }, placementCode: 'pcode000', @@ -30,8 +27,7 @@ describe('Conversant adapter tests', function() { { bidder: 'conversant', params: { - site_id: siteId, - secure: false + site_id: siteId }, mediaTypes: { banner: { @@ -50,8 +46,7 @@ describe('Conversant adapter tests', function() { params: { site_id: siteId, position: 2, - tag_id: '', - secure: false + tag_id: '' }, placementCode: 'pcode002', transactionId: 'tx002', @@ -198,9 +193,15 @@ describe('Conversant adapter tests', function() { }); it('Verify buildRequest', function() { - const request = spec.buildRequests(bidRequests); + const page = 'http://test.com?a=b&c=123'; + const bidderRequest = { + refererInfo: { + referer: page + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.method).to.equal('POST'); - expect(request.url).to.equal('//web.hb.ad.cpe.dotomi.com/s2s/header/24'); + expect(request.url).to.equal('https://web.hb.ad.cpe.dotomi.com/s2s/header/24'); const payload = request.data; expect(payload).to.have.property('id', 'req000'); @@ -209,7 +210,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp).to.be.an('array').with.lengthOf(6); expect(payload.imp[0]).to.have.property('id', 'bid000'); - expect(payload.imp[0]).to.have.property('secure', 0); + expect(payload.imp[0]).to.have.property('secure', 1); expect(payload.imp[0]).to.have.property('bidfloor', 0.5); expect(payload.imp[0]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[0]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -221,7 +222,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[0]).to.not.have.property('video'); expect(payload.imp[1]).to.have.property('id', 'bid001'); - expect(payload.imp[1]).to.have.property('secure', 0); + expect(payload.imp[1]).to.have.property('secure', 1); expect(payload.imp[1]).to.have.property('bidfloor', 0); expect(payload.imp[1]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[1]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -232,7 +233,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[1].banner.format).to.deep.equal([{w: 728, h: 90}, {w: 468, h: 60}]); expect(payload.imp[2]).to.have.property('id', 'bid002'); - expect(payload.imp[2]).to.have.property('secure', 0); + expect(payload.imp[2]).to.have.property('secure', 1); expect(payload.imp[2]).to.have.property('bidfloor', 0); expect(payload.imp[2]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[2]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -242,7 +243,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[2].banner.format).to.deep.equal([{w: 300, h: 600}, {w: 160, h: 600}]); expect(payload.imp[3]).to.have.property('id', 'bid003'); - expect(payload.imp[3]).to.have.property('secure', 0); + expect(payload.imp[3]).to.have.property('secure', 1); expect(payload.imp[3]).to.have.property('bidfloor', 0); expect(payload.imp[3]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[3]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -261,7 +262,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[3]).to.not.have.property('banner'); expect(payload.imp[4]).to.have.property('id', 'bid004'); - expect(payload.imp[4]).to.have.property('secure', 0); + expect(payload.imp[4]).to.have.property('secure', 1); expect(payload.imp[4]).to.have.property('bidfloor', 0); expect(payload.imp[4]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[4]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -280,7 +281,7 @@ describe('Conversant adapter tests', function() { expect(payload.imp[4]).to.not.have.property('banner'); expect(payload.imp[5]).to.have.property('id', 'bid005'); - expect(payload.imp[5]).to.have.property('secure', 0); + expect(payload.imp[5]).to.have.property('secure', 1); expect(payload.imp[5]).to.have.property('bidfloor', 0); expect(payload.imp[5]).to.have.property('displaymanager', 'Prebid.js'); expect(payload.imp[5]).to.have.property('displaymanagerver').that.matches(versionPattern); @@ -299,8 +300,7 @@ describe('Conversant adapter tests', function() { expect(payload).to.have.property('site'); expect(payload.site).to.have.property('id', siteId); expect(payload.site).to.have.property('mobile').that.is.oneOf([0, 1]); - const loc = utils.getTopWindowLocation(); - const page = loc.href; + expect(payload.site).to.have.property('page', page); expect(payload).to.have.property('device'); @@ -365,7 +365,7 @@ describe('Conversant adapter tests', function() { it('Verify publisher commond id support', function() { // clone bidRequests - let requests = utils.deepClone(bidRequests) + let requests = utils.deepClone(bidRequests); // add pubcid to every entry requests.forEach((unit) => { @@ -378,7 +378,7 @@ describe('Conversant adapter tests', function() { it('Verify User ID publisher commond id support', function() { // clone bidRequests - let requests = utils.deepClone(bidRequests) + let requests = utils.deepClone(bidRequests); // add pubcid to every entry requests.forEach((unit) => { @@ -415,4 +415,4 @@ describe('Conversant adapter tests', function() { expect(payload).to.have.deep.nested.property('user.ext.consent', ''); expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr'); }); -}) +}); From 2e7cde2f3e690c9d6e5938ca51b40629402d4f78 Mon Sep 17 00:00:00 2001 From: Nepomuk Seiler Date: Tue, 22 Oct 2019 17:32:18 +0200 Subject: [PATCH 323/436] Add cpmDistribution function for Google Analytics adapter (#4240) * Add cpmDistribution function for Google Analytics adapter * Add test for the cpmDistribution function * Remove half written comment --- modules/googleAnalyticsAdapter.js | 12 ++++++ modules/googleAnalyticsAdapter.md | 37 +++++++++++++++++++ .../modules/googleAnalyticsAdapter_spec.js | 18 +++++++-- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 modules/googleAnalyticsAdapter.md diff --git a/modules/googleAnalyticsAdapter.js b/modules/googleAnalyticsAdapter.js index c1c16019449..2e569cd7ba1 100644 --- a/modules/googleAnalyticsAdapter.js +++ b/modules/googleAnalyticsAdapter.js @@ -19,6 +19,7 @@ var _enableCheck = true; var _category = 'Prebid.js Bids'; var _eventCount = 0; var _enableDistribution = false; +var _cpmDistribution = null; var _trackerSend = null; var _sampled = true; @@ -42,6 +43,9 @@ adapter.enableAnalytics = function ({ provider, options }) { if (options && typeof options.enableDistribution !== 'undefined') { _enableDistribution = options.enableDistribution; } + if (options && typeof options.cpmDistribution === 'function') { + _cpmDistribution = options.cpmDistribution; + } var bid = null; @@ -166,6 +170,9 @@ function getLoadTimeDistribution(time) { } function getCpmDistribution(cpm) { + if (_cpmDistribution) { + return _cpmDistribution(cpm); + } var distribution; if (cpm >= 0 && cpm < 0.5) { distribution = '$0-0.5'; @@ -255,6 +262,11 @@ function sendBidWonToGa(bid) { checkAnalytics(); } +/** + * Exposed for testing purposes + */ +adapter.getCpmDistribution = getCpmDistribution; + adapterManager.registerAnalyticsAdapter({ adapter, code: 'ga' diff --git a/modules/googleAnalyticsAdapter.md b/modules/googleAnalyticsAdapter.md new file mode 100644 index 00000000000..08423a1d492 --- /dev/null +++ b/modules/googleAnalyticsAdapter.md @@ -0,0 +1,37 @@ +# Google Analytics Adapter + +The google analytics adapter pushes prebid events into google analytics. + +## Usage + +The simplest way to enable the analytics adapter is this + +```javascript +pbjs.enableAnalytics([{ + provider: 'ga' +}]); +``` + +Defaults will be used and you should see events being pushed to analytics. + +You can customize the adapter with various `options` like this + +```javascript +pbjs.enableAnalytics([{ + provider: 'ga', + options: { ... } +}]); + +Here is a full list of settings available + +- `global` (string) - name of the global analytics object. Default is `ga` +- `trackerName` (string) - use another tracker for prebid events. Default is the default tracker +- `sampling` (number) - choose a value from `0` to `1`, where `0` means 0% and `1` means 100% tracked +- `enableDistribution` (boolean) - enables additional events that track load time and cpm distribution + by creating buckets for load time and cpm +- `cpmDistribution` (cpm: number => string) - customize the cpm buckets for the cpm distribution + + +## Additional resources + +- [Prebid GA Analytics](http://prebid.org/overview/ga-analytics.html) diff --git a/test/spec/modules/googleAnalyticsAdapter_spec.js b/test/spec/modules/googleAnalyticsAdapter_spec.js index 20517f4138d..6bc0d4e192d 100644 --- a/test/spec/modules/googleAnalyticsAdapter_spec.js +++ b/test/spec/modules/googleAnalyticsAdapter_spec.js @@ -4,12 +4,24 @@ var assert = require('assert'); describe('Ga', function () { describe('enableAnalytics', function () { - it('should accept a tracker name option and output prefixed send string', function () { - var config = { options: { trackerName: 'foo' } }; - ga.enableAnalytics(config); + var cpmDistribution = function(cpm) { + return cpm <= 1 ? '<= 1$' : '> 1$'; + } + var config = { options: { trackerName: 'foo', enableDistribution: true, cpmDistribution: cpmDistribution } }; + + // enableAnalytics can only be called once + ga.enableAnalytics(config); + it('should accept a tracker name option and output prefixed send string', function () { var output = ga.getTrackerSend(); assert.equal(output, 'foo.send'); }); + + it('should use the custom cpm distribution', function() { + assert.equal(ga.getCpmDistribution(0.5), '<= 1$'); + assert.equal(ga.getCpmDistribution(1), '<= 1$'); + assert.equal(ga.getCpmDistribution(2), '> 1$'); + assert.equal(ga.getCpmDistribution(5.23), '> 1$'); + }); }); }); From fe73e5d8e572ac34d22a4ed3d30625963421e383 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 22 Oct 2019 10:30:18 -0700 Subject: [PATCH 324/436] fixing SRA p_pos (#4337) --- modules/rubiconBidAdapter.js | 5 ++- test/spec/modules/rubiconBidAdapter_spec.js | 36 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index cc17e259695..7885158425b 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -410,9 +410,8 @@ export const spec = { }; // add p_pos only if specified and valid - if (params.position === 'atf' || params.position === 'btf') { - data['p_pos'] = params.position; - } + // For SRA we need to explicitly put empty semi colons so AE treats it as empty, instead of copying the latter value + data['p_pos'] = (params.position === 'atf' || params.position === 'btf') ? params.position : ''; if ((bidRequest.userId || {}).tdid) { data['tpid_tdid'] = bidRequest.userId.tdid; diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 4688f0f5d32..0390d4598ae 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -375,6 +375,42 @@ describe('the rubicon adapter', function () { expect(data['p_pos']).to.equal(undefined); }); + it('should correctly send p_pos in sra fashion', function() { + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'rubicon.singleRequest': true + }; + return config[key]; + }); + // first one is atf + var sraPosRequest = utils.deepClone(bidderRequest); + + // second is not present + const bidCopy = utils.deepClone(sraPosRequest.bids[0]); + delete bidCopy.params.position; + sraPosRequest.bids.push(bidCopy); + + // third is btf + const bidCopy1 = utils.deepClone(sraPosRequest.bids[0]); + bidCopy1.params.position = 'btf'; + sraPosRequest.bids.push(bidCopy1); + + // fourth is invalid (aka not atf or btf) + const bidCopy2 = utils.deepClone(sraPosRequest.bids[0]); + bidCopy2.params.position = 'unknown'; + sraPosRequest.bids.push(bidCopy2); + + // fifth is not present + const bidCopy3 = utils.deepClone(sraPosRequest.bids[0]); + delete bidCopy3.params.position; + sraPosRequest.bids.push(bidCopy3); + + let [request] = spec.buildRequests(sraPosRequest.bids, sraPosRequest); + let data = parseQuery(request.data); + + expect(data['p_pos']).to.equal('atf;;btf;;'); + }); + it('ad engine query params should be ordered correctly', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); From 8678764dc9e3d0a5dcb2e6bdcbadf2b003f26e73 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Tue, 22 Oct 2019 13:36:45 -0400 Subject: [PATCH 325/436] In Sonobi Adapter, only read sizes from bid.mediaTypes (#4311) --- modules/sonobiBidAdapter.js | 43 +++- test/spec/modules/sonobiBidAdapter_spec.js | 279 +++++++++++++++------ 2 files changed, 248 insertions(+), 74 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index a0390a981a5..3fb9a83d259 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -20,8 +20,36 @@ export const spec = { * @param {BidRequest} bid - The bid params to validate. * @return {boolean} True if this is a valid bid, and false otherwise. */ - isBidRequestValid: bid => !!(bid.params && (bid.params.ad_unit || bid.params.placement_id) && (bid.params.sizes || bid.sizes)), + isBidRequestValid: (bid) => { + if (!bid.params) { + return false; + } + if (!bid.params.ad_unit && !bid.params.placement_id) { + return false; + } + + if (!deepAccess(bid, 'mediaTypes.banner') && !deepAccess(bid, 'mediaTypes.video')) { + return false; + } + if (deepAccess(bid, 'mediaTypes.banner')) { // Sonobi does not support multi type bids, favor banner over video + if (!deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.sizes) { + // sizes at the banner or params level is required. + return false; + } + } else if (deepAccess(bid, 'mediaTypes.video')) { + if (deepAccess(bid, 'mediaTypes.video.context') === 'outstream' && !bid.params.sizes) { + // bids.params.sizes is required for outstream video adUnits + return false; + } + if (deepAccess(bid, 'mediaTypes.video.context') === 'instream' && !deepAccess(bid, 'mediaTypes.video.playerSize')) { + // playerSize is required for instream adUnits. + return false; + } + } + + return true; + }, /** * Make a server request from the list of BidRequests. * @@ -227,10 +255,21 @@ function _findBidderRequest(bidderRequests, bidId) { } function _validateSize (bid) { + if (deepAccess(bid, 'mediaTypes.video')) { + return ''; // Video bids arent allowed to override sizes via the trinity request + } + if (bid.params.sizes) { return parseSizesInput(bid.params.sizes).join(','); } - return parseSizesInput(bid.sizes).join(','); + if (deepAccess(bid, 'mediaTypes.banner.sizes')) { + return parseSizesInput(deepAccess(bid, 'mediaTypes.banner.sizes')).join(','); + } + + // Handle deprecated sizes definition + if (bid.sizes) { + return parseSizesInput(bid.sizes).join(','); + } } function _validateSlot (bid) { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index dc536846ae2..a6bf88cfc74 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -19,87 +19,222 @@ describe('SonobiBidAdapter', function () { }) describe('.isBidRequestValid', function () { - let bid = { - 'bidder': 'sonobi', - 'params': { - 'ad_unit': '/7780971/sparks_prebid_MR', - 'sizes': [[300, 250], [300, 600]], - 'floor': '1' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - - it('should return true when bid.params.placement_id and bid.params.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - delete bid.sizes - bid.params = { - 'placement_id': '1a2b3c4d5e6f1a2b3c4d', - 'sizes': [[300, 250], [300, 600]], - } + it('should return false if there are no params', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + it('should return false if there is no placement_id param and no ad_unit param', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placementId: '1a2b3c4d5e6f1a2b3c4d', + }, + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - it('should return true when bid.params.placement_id and bid.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - bid.sizes = [[300, 250], [300, 600]] - bid.params = { - 'placement_id': '1a2b3c4d5e6f1a2b3c4d', - } + it('should return false if there is no mediaTypes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + it('should return true if the bid is valid', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); - it('should return true when bid.params.ad_unit and bid.params.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - delete bid.sizes - bid.params = { - 'ad_unit': '/7780971/sparks_prebid_MR', - 'sizes': [[300, 250], [300, 600]], - } + describe('banner', () => { + it('should return false if there are no banner sizes and no param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + banner: { - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); - it('should return true when bid.params.ad_unit and bid.sizes are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - bid.sizes = [[300, 250], [300, 600]] - bid.params = { - 'ad_unit': '/7780971/sparks_prebid_MR', - } + it('should return true if there is banner sizes and no param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d' + }, + 'mediaTypes': { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) + it('should return true if there is param sizes and no banner sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + sizes: [[300, 250], [300, 600]] + }, + 'mediaTypes': { + banner: { + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); - it('should return false when no params are found', function () { - let bid = Object.assign({}, bid) - delete bid.params - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) + describe('video', () => { + describe('instream', () => { + it('should return false if there is no playerSize defined in the video mediaType', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + sizes: [[300, 250], [300, 600]] + }, + 'mediaTypes': { + video: { + context: 'instream' + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true if there is playerSize defined on the video mediaType', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + }, + 'mediaTypes': { + video: { + context: 'instream', + playerSize: [300, 250] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); - it('should return false when bid.params.placement_id and bid.params.ad_unit are not found', function () { - let bid = Object.assign({}, bid) - delete bid.params - bid.params = { - 'placement_id': 0, - 'ad_unit': 0, - 'sizes': [[300, 250], [300, 600]], - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - }) + describe('outstream', () => { + it('should return false if there is no param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + }, + 'mediaTypes': { + video: { + context: 'outstream', + playerSize: [300, 250] + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true if there is param sizes', () => { + const bid = { + 'bidder': 'sonobi', + 'adUnitCode': 'adunit-code', + params: { + placement_id: '1a2b3c4d5e6f1a2b3c4d', + sizes: [300, 250] + + }, + 'mediaTypes': { + video: { + context: 'outstream' + } + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + }); + }); describe('.buildRequests', function () { beforeEach(function() { From a24e76e1c07f49806f3ac7647cd5ba263cc331cb Mon Sep 17 00:00:00 2001 From: TinchoF <50110327+TinchoF@users.noreply.github.com> Date: Tue, 22 Oct 2019 15:54:08 -0300 Subject: [PATCH 326/436] Fix mediaTypes (#4332) * Outcon bid adapter. * Fix identation * Fixes * Fixes * Fixes * Spec fixes * Fixes * Fix urls * Fix * Fix parameters * Fix space operators * Fix bidder timeout * Update * Fix whitespace * no message * Outcon unit test * no message * no message * no message * no message * Fixes * Fixes * Change url * no message * no message * no message * Added bidId * no message * no message * no message * no message * Wrapping url with html * no message * no message * no message * Fix mediaTypes * no message * Update outconBidAdapter_spec.js * Adding VAS response * no message * no message * no message * Fix * Changed ttl * no message * supportedMediaTypes * no message * no message --- modules/outconBidAdapter.js | 18 ++++++++++++++---- test/spec/modules/outconBidAdapter_spec.js | 13 +++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/outconBidAdapter.js b/modules/outconBidAdapter.js index d691e807059..ba0c1164279 100644 --- a/modules/outconBidAdapter.js +++ b/modules/outconBidAdapter.js @@ -1,18 +1,20 @@ import {registerBidder} from '../src/adapters/bidderFactory'; -import {config} from '../src/config'; const BIDDER_CODE = 'outcon'; + export const spec = { code: BIDDER_CODE, + supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function(bid) { return !!((bid.params.pod || (bid.params.internalId && bid.params.publisher)) && bid.params.env); }, buildRequests: function(validBidRequests) { for (let i = 0; i < validBidRequests.length; i++) { - let par = ''; let url = ''; + let par = ''; if (validBidRequests[i].params.pod != undefined) par = 'get?pod=' + validBidRequests[i].params.pod + '&bidId=' + validBidRequests[i].bidId; else par = 'get?internalId=' + validBidRequests[i].params.internalId + '&publisher=' + validBidRequests[i].params.publisher + '&bidId=' + validBidRequests[i].bidId; + par = par + '&vast=true'; switch (validBidRequests[i].params.env) { case 'test': par = par + '&demo=true'; @@ -42,10 +44,17 @@ export const spec = { creativeId: serverResponse.body.creatives[0].id, currency: serverResponse.body.cur, netRevenue: true, - ttl: config.getConfig('_bidderTimeout'), + ttl: 300, ad: wrapDisplayUrl(serverResponse.body.creatives[0].url, serverResponse.body.type), - vastImpUrl: serverResponse.body.trackingURL + vastImpUrl: serverResponse.body.trackingURL, + mediaType: serverResponse.body.type }; + if (serverResponse.body.type == 'video') { + Object.assign(bidResponse, { + vastUrl: serverResponse.body.vastURL, + ttl: 3600 + }); + } bidResponses.push(bidResponse); return bidResponses; }, @@ -54,6 +63,7 @@ export const spec = { function wrapDisplayUrl(displayUrl, type) { if (type == 'video') return `
`; if (type == 'banner') return `
`; + return null; } registerBidder(spec); diff --git a/test/spec/modules/outconBidAdapter_spec.js b/test/spec/modules/outconBidAdapter_spec.js index dc9c96ed3a3..a263bc9dbf9 100644 --- a/test/spec/modules/outconBidAdapter_spec.js +++ b/test/spec/modules/outconBidAdapter_spec.js @@ -23,6 +23,7 @@ describe('outconBidAdapter', function () { })).to.equal(true); }); }); + describe('buildRequests', function () { it('Build requests with pod param', function () { expect(spec.buildRequests([{ @@ -52,7 +53,8 @@ describe('outconBidAdapter', function () { url: 'http://test.outcondigital.com:8048/ad/', data: { pod: '5d603538eba7192ae14e39a4', - env: 'test' + env: 'test', + vast: 'true' } }; const bidResponse = { @@ -69,10 +71,11 @@ describe('outconBidAdapter', function () { codec: 'video/mp4' } ], - id: '5d6e6aef22063e392bf7f564', + ad: '5d6e6aef22063e392bf7f564', type: 'video', campaign: '5d42e44b306ea469593c76a2', - trackingURL: 'http://test.outcondigital.com:8048/ad/track?track=5d6e6aef22063e392bf7f564' + trackingURL: 'http://test.outcondigital.com:8048/ad/track?track=5d6e6aef22063e392bf7f564', + vastURL: 'http://test.outcondigital.com:8048/outcon.xml?impression=5d6e6aef22063e392bf7f564&demo=true' }, }; it('check all the keys that are needed to interpret the response', function () { @@ -87,7 +90,9 @@ describe('outconBidAdapter', function () { 'netRevenue', 'ttl', 'ad', - 'vastImpUrl' + 'vastImpUrl', + 'mediaType', + 'vastUrl' ]; let resultKeys = Object.keys(result[0]); resultKeys.forEach(function(key) { From 9b556d7e1ffa5d2ebaa8566747791b529069d3a0 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 22 Oct 2019 15:41:07 -0400 Subject: [PATCH 327/436] Prebid 2.37.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0200db4eace..0228e16ff55 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.37.0-pre", + "version": "2.37.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 890121c4f059526d697600b6fb5b3602d69e0bfd Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Tue, 22 Oct 2019 15:50:06 -0400 Subject: [PATCH 328/436] increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0228e16ff55..9e5effb8627 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.37.0", + "version": "2.38.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 15cca9a6cd84c09efe64ac04ccbf9ed2f1e97274 Mon Sep 17 00:00:00 2001 From: John Salis Date: Wed, 23 Oct 2019 10:35:48 -0400 Subject: [PATCH 329/436] Add vast xml support and other minor changes to Beachfront adapter (#4350) * Add support for vast xml in the bid response * add secure protocol to outstream player url * add device connection type * add player setting for poster color * add new value for creative Id --- modules/beachfrontBidAdapter.js | 19 +++++-- modules/beachfrontBidAdapter.md | 1 + .../spec/modules/beachfrontBidAdapter_spec.js | 55 +++++++++++++++++-- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 0143f01835d..49b6b0c4edb 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,13 +7,13 @@ 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.7'; +const ADAPTER_VERSION = '1.8'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; export const VIDEO_ENDPOINT = 'https://reachms.bfmio.com/bid.json?exchange_id='; export const BANNER_ENDPOINT = 'https://display.bfmio.com/prebid_display'; -export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; +export const OUTSTREAM_SRC = 'https://player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js'; export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'placement']; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; @@ -68,10 +68,11 @@ export const spec = { requestId: bidRequest.bidId, bidderCode: spec.code, vastUrl: response.url, + vastXml: response.vast, cpm: response.bidPrice, width: firstSize.w, height: firstSize.h, - creativeId: response.cmpId, + creativeId: response.crid || response.cmpId, renderer: context === OUTSTREAM ? createRenderer(bidRequest) : null, mediaType: VIDEO, currency: 'USD', @@ -151,7 +152,8 @@ function createRenderer(bidRequest) { height: bid.height, expandInView: getPlayerBidParam(bidRequest, 'expandInView', false), collapseOnComplete: getPlayerBidParam(bidRequest, 'collapseOnComplete', true), - progressColor: getPlayerBidParam(bidRequest, 'progressColor') + progressColor: getPlayerBidParam(bidRequest, 'progressColor'), + adPosterColor: getPlayerBidParam(bidRequest, 'adPosterColor') }); }); }); @@ -284,7 +286,9 @@ function createVideoRequestData(bid, bidderRequest) { mimes: DEFAULT_MIMES }, video), bidfloor: bidfloor, - secure: topLocation.protocol === 'https:' ? 1 : 0 + secure: topLocation.protocol === 'https:' ? 1 : 0, + displaymanager: ADAPTER_NAME, + displaymanagerver: ADAPTER_VERSION }], site: { page: topLocation.href, @@ -325,6 +329,11 @@ function createVideoRequestData(bid, bidderRequest) { }]; } + let connection = navigator.connection || navigator.webkitConnection; + if (connection && connection.effectiveType) { + payload.device.connectiontype = connection.effectiveType; + } + return payload; } diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 3f827fe9241..0a6b8b73da4 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -109,6 +109,7 @@ Module that connects to Beachfront's demand sources }, player: { progressColor: '#50A8FA', + adPosterColor: '#FFF', expandInView: false, collapseOnComplete: true } diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 4598a4e00c7..155da4fb309 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -496,15 +496,16 @@ describe('BeachfrontAdapter', function () { const serverResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', - cmpId: '123abc' + crid: '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, + creativeId: serverResponse.crid, vastUrl: serverResponse.url, + vastXml: undefined, width: width, height: height, renderer: null, @@ -515,6 +516,48 @@ describe('BeachfrontAdapter', function () { }); }); + it('should default to the legacy "cmpId" value for the creative ID', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + 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 }); + expect(bidResponse).to.deep.contain({ + creativeId: serverResponse.cmpId + }); + }); + + it('should return vast xml if found on the bid response', () => { + const width = 640; + const height = 480; + const bidRequest = bidRequests[0]; + bidRequest.mediaTypes = { + video: { + playerSize: [ width, height ] + } + }; + const serverResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + vast: '', + crid: '123abc' + }; + const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); + expect(bidResponse).to.deep.contain({ + vastUrl: serverResponse.url, + vastXml: serverResponse.vast + }); + }); + it('should return a renderer for outstream video bids', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { @@ -525,7 +568,7 @@ describe('BeachfrontAdapter', function () { const serverResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', - cmpId: '123abc' + crid: '123abc' }; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.renderer).to.deep.contain({ @@ -547,7 +590,7 @@ describe('BeachfrontAdapter', function () { const serverResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', - cmpId: '123abc' + crid: '123abc' }; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); window.Beachfront = { Player: sinon.spy() }; @@ -581,7 +624,7 @@ describe('BeachfrontAdapter', function () { const serverResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', - cmpId: '123abc' + crid: '123abc' }; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); window.Beachfront = { Player: sinon.spy() }; @@ -662,7 +705,7 @@ describe('BeachfrontAdapter', function () { bidResponse = { bidPrice: 5.00, url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', - cmpId: '123abc' + crid: '123abc' }; }); From b585eeab975fa08c077ba3a0d156b0788df6be44 Mon Sep 17 00:00:00 2001 From: evanmsmrtb Date: Wed, 23 Oct 2019 10:14:50 -0500 Subject: [PATCH 330/436] Update smartrtbBidAdapter (#4362) * modules: Implement SmartRTB adapter and spec. * Fix for-loop syntax to support IE; refactor getDomain out of exported set. * Remove debugs, update doc * Update test for video support * Handle missing syncs. Add video to media types in sample ad unit * Add null response check, update primary endpoint * Note smrtb video requires renderer * Remove old params checks, fix documentation playerSize field name --- modules/smartrtbBidAdapter.js | 5 +---- modules/smartrtbBidAdapter.md | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/smartrtbBidAdapter.js b/modules/smartrtbBidAdapter.js index f99c4a58680..10d23a0ccc7 100644 --- a/modules/smartrtbBidAdapter.js +++ b/modules/smartrtbBidAdapter.js @@ -17,11 +17,8 @@ function getDomain () { export const spec = { code: BIDDER_CODE, supportedMediaTypes: [ 'banner', 'video' ], - aliases: ['smrtb'], isBidRequestValid: function(bid) { - return (bid.params.pubId !== null && - bid.params.medId !== null && - bid.params.zoneId !== null); + return (bid.params.zoneId !== null); }, buildRequests: function(validBidRequests, bidderRequest) { let stack = (bidderRequest.refererInfo && diff --git a/modules/smartrtbBidAdapter.md b/modules/smartrtbBidAdapter.md index c44903114cf..7db07ae3fa1 100644 --- a/modules/smartrtbBidAdapter.md +++ b/modules/smartrtbBidAdapter.md @@ -24,7 +24,7 @@ Video is supported but requires a publisher supplied adunit renderer at this tim }, video: { /* requires publisher supplied renderer */ context: 'outstream', - playerDimension: [640, 480] + playerSize: [640, 480] } }, bids: [ From 290c265c29140e4f205dc6ec336b065500fa9a97 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Wed, 23 Oct 2019 11:51:33 -0400 Subject: [PATCH 331/436] Revert "Update smartrtbBidAdapter (#4362)" (#4368) This reverts commit be6704bcec65a28d80b6d09a8d1c51ef9a8ba824. --- modules/smartrtbBidAdapter.js | 5 ++++- modules/smartrtbBidAdapter.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/smartrtbBidAdapter.js b/modules/smartrtbBidAdapter.js index 10d23a0ccc7..f99c4a58680 100644 --- a/modules/smartrtbBidAdapter.js +++ b/modules/smartrtbBidAdapter.js @@ -17,8 +17,11 @@ function getDomain () { export const spec = { code: BIDDER_CODE, supportedMediaTypes: [ 'banner', 'video' ], + aliases: ['smrtb'], isBidRequestValid: function(bid) { - return (bid.params.zoneId !== null); + return (bid.params.pubId !== null && + bid.params.medId !== null && + bid.params.zoneId !== null); }, buildRequests: function(validBidRequests, bidderRequest) { let stack = (bidderRequest.refererInfo && diff --git a/modules/smartrtbBidAdapter.md b/modules/smartrtbBidAdapter.md index 7db07ae3fa1..c44903114cf 100644 --- a/modules/smartrtbBidAdapter.md +++ b/modules/smartrtbBidAdapter.md @@ -24,7 +24,7 @@ Video is supported but requires a publisher supplied adunit renderer at this tim }, video: { /* requires publisher supplied renderer */ context: 'outstream', - playerSize: [640, 480] + playerDimension: [640, 480] } }, bids: [ From 0a7d59f281d78df71c6298cb887c53f12c19cc8d Mon Sep 17 00:00:00 2001 From: OneTagDevOps <38786435+OneTagDevOps@users.noreply.github.com> Date: Wed, 23 Oct 2019 21:52:12 +0200 Subject: [PATCH 332/436] Add userSync in onetagBidAdapter (#4358) * Minor bug fixing in onetagBidAdapter.js Fixed a minor bug. Updated TTL in response to align the correct specifications. * Update onetagBidAdapter Added additional page info and user sync function. * Update onetagBidAdapter_spec.js Added the test for getUserSyncs function. * Fix about userSync * getUserSyncs: test update with gdpr params --- modules/onetagBidAdapter.js | 30 +++++++++++ test/spec/modules/onetagBidAdapter_spec.js | 61 +++++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index ce671772dad..77c257fd7fb 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -3,6 +3,7 @@ const { registerBidder } = require('../src/adapters/bidderFactory'); const ENDPOINT = 'https://onetag-sys.com/prebid-request'; +const USER_SYNC_ENDPOINT = 'https://onetag-sys.com/usync/'; const BIDDER_CODE = 'onetag'; const BANNER = 'banner'; @@ -120,8 +121,15 @@ function getPageInfo() { masked: m, wWidth: w.innerWidth, wHeight: w.innerHeight, + oWidth: w.outerWidth, + oHeight: w.outerHeight, sWidth: s.width, sHeight: s.height, + aWidth: s.availWidth, + aHeight: s.availHeight, + sLeft: 'screenLeft' in w ? w.screenLeft : w.screenX, + sTop: 'screenTop' in w ? w.screenTop : w.screenY, + hLength: history.length, date: t.toUTCString(), timeOffset: t.getTimezoneOffset() }; @@ -162,6 +170,27 @@ function requestsToBids(bid) { return toRet; } +function getUserSyncs(syncOptions, serverResponses, gdprConsent) { + const syncs = []; + if (syncOptions.iframeEnabled) { + const rnd = new Date().getTime(); + let params = '?cb=' + rnd; + + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + params += '&gdpr_consent=' + gdprConsent.consentString; + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); + } + } + + syncs.push({ + type: 'iframe', + url: USER_SYNC_ENDPOINT + params + }); + } + return syncs; +} + export const spec = { code: BIDDER_CODE, @@ -170,6 +199,7 @@ export const spec = { isBidRequestValid: isBidRequestValid, buildRequests: buildRequests, interpretResponse: interpretResponse, + getUserSyncs: getUserSyncs }; diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index d56ad9e6dc5..93284566069 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -53,7 +53,7 @@ describe('onetag', function () { const data = JSON.parse(d); it('Should contains all keys', function () { expect(data).to.be.an('object'); - expect(data).to.have.all.keys('location', 'masked', 'referrer', 'sHeight', 'sWidth', 'timeOffset', 'date', 'wHeight', 'wWidth', 'bids'); + expect(data).to.have.all.keys('location', 'masked', 'referrer', 'sHeight', 'sWidth', 'timeOffset', 'date', 'wHeight', 'wWidth', 'oHeight', 'oWidth', 'aWidth', 'aHeight', 'sLeft', 'sTop', 'hLength', 'bids'); expect(data.location).to.be.a('string'); expect(data.masked).to.be.a('number'); expect(data.referrer).to.be.a('string'); @@ -61,6 +61,13 @@ describe('onetag', function () { expect(data.sWidth).to.be.a('number'); expect(data.wWidth).to.be.a('number'); expect(data.wHeight).to.be.a('number'); + expect(data.oHeight).to.be.a('number'); + expect(data.oWidth).to.be.a('number'); + expect(data.aWidth).to.be.a('number'); + expect(data.aHeight).to.be.a('number'); + expect(data.sLeft).to.be.a('number'); + expect(data.sTop).to.be.a('number'); + expect(data.hLength).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'); @@ -146,4 +153,56 @@ describe('onetag', function () { }); }); }); + describe('getUserSyncs', function () { + const sync_endpoint = 'https://onetag-sys.com/usync/'; + it('Returns an iframe if iframeEnabled is true', function () { + const syncs = spec.getUserSyncs({iframeEnabled: true}); + expect(syncs).to.be.an('array'); + expect(syncs.length).to.equal(1); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.include(sync_endpoint); + }); + it('Returns an empty array if iframeEnabled is false', function () { + const syncs = spec.getUserSyncs({ iframeEnabled: false }); + expect(syncs).to.be.an('array').that.is.empty; + }); + it('Must pass gdpr params when gdprApplies is true', function () { + const syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, { + gdprApplies: true, consentString: 'foo' + }); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.include(sync_endpoint); + expect(syncs[0].url).to.match(/(?:[?&](?:gdpr_consent=foo([^&]*)|gdpr=1([^&]*)|[^&]*))+$/); + }); + it('Must pass gdpr params when gdprApplies is false', function () { + const syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, { + gdprApplies: false, consentString: 'foo' + }); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.include(sync_endpoint); + expect(syncs[0].url).to.match(/(?:[?&](?:gdpr_consent=foo([^&]*)|gdpr=0([^&]*)))+$/); + }); + it('Must pass gdpr consent string param when gdprApplies is undefined', function () { + const syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, { + consentString: 'foo' + }); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.include(sync_endpoint); + expect(syncs[0].url).to.match(/(?:[?&](?:gdpr_consent=foo([^&]*)))+$/); + }); + it('Must pass no gdpr params when consentString is null', function () { + const syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, { + consentString: null + }); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.include(sync_endpoint); + expect(syncs[0].url).to.not.match(/(?:[?&](?:gdpr_consent=([^&]*)|gdpr=([^&]*)))+$/); + }); + it('Must pass no gdpr param when gdprConsent is empty', function () { + const syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, {}); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.include(sync_endpoint); + expect(syncs[0].url).to.not.match(/(?:[?&](?:gdpr_consent=([^&]*)|gdpr=([^&]*)))+$/); + }); + }); }); From 8d8507087037723585a6cf48d632821a4a06378c Mon Sep 17 00:00:00 2001 From: Ankit Prakash Date: Wed, 23 Oct 2019 12:52:32 -0700 Subject: [PATCH 333/436] Sovrn adapter updates: schain, digitrust, pixel syncing, and 3.0 upgrades (#4335) * schain and digitrust * pixel beacons * unit tests and fixes from testing * Prebid 3.0 updates * review fix --- modules/sovrnBidAdapter.js | 134 +++++----- test/spec/modules/sovrnBidAdapter_spec.js | 286 ++++++++++++++-------- 2 files changed, 248 insertions(+), 172 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 8b08b3ad6be..935bbad79a7 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,8 +1,6 @@ import * as utils from '../src/utils' import { registerBidder } from '../src/adapters/bidderFactory' import { BANNER } from '../src/mediaTypes' -const errorUrl = 'https://pcb.aws.lijit.com/c' -let errorpxls = [] export const spec = { code: 'sovrn', @@ -24,14 +22,30 @@ export const spec = { */ buildRequests: function(bidReqs, bidderRequest) { try { - const loc = utils.getTopWindowLocation(); let sovrnImps = []; let iv; + let schain; + let digitrust; + utils._each(bidReqs, function (bid) { + if (!digitrust) { + const bidRequestDigitrust = utils.deepAccess(bid, 'userId.digitrustid.data'); + if (bidRequestDigitrust && (!bidRequestDigitrust.privacy || !bidRequestDigitrust.privacy.optout)) { + digitrust = { + id: bidRequestDigitrust.id, + keyv: bidRequestDigitrust.keyv + } + } + } + if (bid.schain) { + schain = schain || bid.schain; + } iv = iv || utils.getBidIdParameter('iv', bid.params); - bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]) - bid.sizes = bid.sizes.filter(size => utils.isArray(size)) - const processedSizes = bid.sizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) + + let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; + bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]) + bidSizes = bidSizes.filter(size => utils.isArray(size)) + const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) sovrnImps.push({ id: bid.bidId, banner: { @@ -43,15 +57,30 @@ export const spec = { bidfloor: utils.getBidIdParameter('bidfloor', bid.params) }); }); + + const page = bidderRequest.refererInfo.referer + // clever trick to get the domain + const el = document.createElement('a'); + el.href = page; + const domain = el.hostname; + const sovrnBidReq = { id: utils.getUniqueIdentifierStr(), imp: sovrnImps, site: { - domain: loc.host, - page: loc.host + loc.pathname + loc.search + loc.hash + page, + domain } }; + if (schain) { + sovrnBidReq.source = { + ext: { + schain + } + }; + } + if (bidderRequest && bidderRequest.gdprConsent) { sovrnBidReq.regs = { ext: { @@ -63,7 +92,14 @@ export const spec = { }}; } - let url = `//ap.lijit.com/rtb/bid?` + + if (digitrust) { + utils.deepSetValue(sovrnBidReq, 'user.ext.digitrust', { + id: digitrust.id, + keyv: digitrust.keyv + }) + } + + let url = `https://ap.lijit.com/rtb/bid?` + `src=$$REPO_AND_VERSION$$`; if (iv) url += `&iv=${iv}`; @@ -74,7 +110,8 @@ export const spec = { options: {contentType: 'text/plain'} } } catch (e) { - new LogError(e, {bidReqs, bidderRequest}).append() + console.log('error in build:') + console.log(e) } }, @@ -109,74 +146,43 @@ export const spec = { } return sovrnBidResponses } catch (e) { - new LogError(e, {id, seatbid}).append() + console.log('error in interpret:') + console.log(e) } }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { try { let tracks = [] - if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { - let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) - .map(rsp => { return rsp.body.ext.iid }); - let consentString = ''; - if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { - consentString = gdprConsent.consentString + if (serverResponses && serverResponses.length !== 0) { + if (syncOptions.iframeEnabled) { + let iidArr = serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.iid')) + .map(resp => resp.body.ext.iid); + let consentString = ''; + if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + consentString = gdprConsent.consentString + } + if (iidArr[0]) { + tracks.push({ + type: 'iframe', + url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, + }); + } } - if (iidArr[0]) { - tracks.push({ - type: 'iframe', - url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, - }); + + if (syncOptions.pixelEnabled) { + serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.sync.pixels')) + .flatMap(resp => resp.body.ext.sync.pixels) + .map(pixel => pixel.url) + .forEach(url => tracks.push({ type: 'image', url })) } } - if (errorpxls.length && syncOptions.pixelEnabled) { - tracks = tracks.concat(errorpxls) - } + return tracks } catch (e) { - if (syncOptions.pixelEnabled) { - return errorpxls - } return [] } }, } -export class LogError { - constructor(e, data) { - utils.logError(e) - this.error = {} - this.error.t = utils.timestamp() - this.error.m = e.message - this.error.s = e.stack - this.error.d = data - this.error.v = $$REPO_AND_VERSION$$ - this.error.u = utils.getTopWindowLocation().href - this.error.ua = navigator.userAgent - } - buildErrorString(obj) { - return errorUrl + '?b=' + btoa(JSON.stringify(obj)) - } - append() { - let errstr = this.buildErrorString(this.error) - if (errstr.length > 2083) { - delete this.error.d - errstr = this.buildErrorString(this.error) - if (errstr.length > 2083) { - delete this.error.s - errstr = this.buildErrorString(this.error) - if (errstr.length > 2083) { - errstr = this.buildErrorString({m: 'unknown error message', t: this.error.t, u: this.error.u}) - } - } - } - let obj = {type: 'image', url: errstr} - errorpxls.push(obj) - } - static getErrPxls() { - return errorpxls - } -} - registerBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 7179ec00bc3..af27e6e74a6 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,9 +1,8 @@ -import { expect } from 'chai'; -import { spec, LogError } from 'modules/sovrnBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; -import { SSL_OP_SINGLE_ECDH_USE } from 'constants'; +import {expect} from 'chai'; +import {LogError, spec} from 'modules/sovrnBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT = `//ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; +const ENDPOINT = `https://ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; describe('sovrnBidAdapter', function() { const adapter = newBidder(spec); @@ -55,8 +54,12 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - - const request = spec.buildRequests(bidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); @@ -73,7 +76,7 @@ describe('sovrnBidAdapter', function() { expect(payload.imp[0].banner.h).to.equal(1) }) - it('accepts a single array as a size', function() { + it('accepts a single array as a size', () => { const singleSize = [{ 'bidder': 'sovrn', 'params': { @@ -85,8 +88,13 @@ describe('sovrnBidAdapter', function() { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' - }]; - const request = spec.buildRequests(singleSize) + }] + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + } + const request = spec.buildRequests(singleSize, bidderRequest) const payload = JSON.parse(request.data) expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]) expect(payload.imp[0].banner.w).to.equal(1) @@ -109,7 +117,12 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const request = spec.buildRequests(ivBidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const request = spec.buildRequests(ivBidRequests, bidderRequest); expect(request.url).to.contain('iv=vet') }); @@ -121,20 +134,22 @@ describe('sovrnBidAdapter', function() { 'auctionId': '1d1a030790a475', 'bidderRequestId': '22edbae2733bf6', 'timeout': 3000, - 'gdprConsent': { + gdprConsent: { consentString: consentString, gdprApplies: true + }, + refererInfo: { + referer: 'http://example.com/page.html', } }; bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); + const data = JSON.parse(spec.buildRequests(bidRequests, bidderRequest).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); + expect(data.regs.ext.gdpr).to.exist.and.to.be.a('number'); + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.user.ext.consent).to.exist.and.to.be.a('string'); + expect(data.user.ext.consent).to.equal(consentString); }); it('converts tagid to string', function () { @@ -153,10 +168,86 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const request = spec.buildRequests(ivBidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const request = spec.buildRequests(ivBidRequests, bidderRequest); expect(request.data).to.contain('"tagid":"403370"') - }) + }); + + it('should add schain if present', () => { + const schainRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': 403370 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'directseller.com', + 'sid': '00001', + 'rid': 'BidRequest1', + 'hp': 1 + } + ] + } + }].concat(bidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const data = JSON.parse(spec.buildRequests(schainRequests, bidderRequest).data); + + expect(data.source.ext.schain.nodes.length).to.equal(1) + }); + + it('should add digitrust data if present', () => { + const digitrustRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': 403370 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'userId': { + 'digitrustid': { + 'data': { + 'id': 'digitrust-id-123', + 'keyv': 4 + } + } + } + }].concat(bidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const data = JSON.parse(spec.buildRequests(digitrustRequests, bidderRequest).data); + + expect(data.user.ext.digitrust.id).to.equal('digitrust-id-123'); + expect(data.user.ext.digitrust.keyv).to.equal(4); + }); }); describe('interpretResponse', function () { @@ -254,8 +345,8 @@ describe('sovrnBidAdapter', function() { }); describe('getUserSyncs ', () => { - let syncOptions = {iframeEnabled: true, pixelEnabled: true}; - let iframeDisabledSyncOptions = {iframeEnabled: false, pixelEnabled: true}; + let syncOptions = { iframeEnabled: true, pixelEnabled: false }; + let iframeDisabledSyncOptions = { iframeEnabled: false, pixelEnabled: false }; let serverResponse = [ { 'body': { @@ -287,111 +378,90 @@ describe('sovrnBidAdapter', function() { } ], 'ext': { - 'iid': 13487408 + 'iid': 13487408, + sync: { + pixels: [ + { + url: 'http://idprovider1.com' + }, + { + url: 'http://idprovider2.com' + } + ] + } } }, 'headers': {} } ]; + it('should return if iid present on server response & iframe syncs enabled', () => { - let expectedReturnStatement = [ + const expectedReturnStatement = [ { 'type': 'iframe', 'url': '//ap.lijit.com/beacon?informer=13487408&gdpr_consent=', } - ] - let returnStatement = spec.getUserSyncs(syncOptions, serverResponse); + ]; + const returnStatement = spec.getUserSyncs(syncOptions, serverResponse); expect(returnStatement[0]).to.deep.equal(expectedReturnStatement[0]); - }) + }); it('should not return if iid missing on server response', () => { - let returnStatement = spec.getUserSyncs(syncOptions, []) + const returnStatement = spec.getUserSyncs(syncOptions, []); expect(returnStatement).to.be.empty; - }) + }); it('should not return if iframe syncs disabled', () => { - let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse) - expect(returnStatement).to.be.empty - }) - }) - describe('LogError', () => { - it('should build and append an error object', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const data = {name: 'Oscar Hathenswiotch'} - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(1) - const errdata = JSON.parse(atob(errList[0].url.split('=')[1])) - expect(errdata.d.name).to.equal('Oscar Hathenswiotch') - }) - it('should drop data when there is too much', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const tooLong = () => { - let str = '' - for (let i = 0; i < 10000; i++) { - str = str + String.fromCharCode(i % 100) - } - return str - } - const data = {name: 'Oscar Hathenswiotch', tooLong: tooLong()} - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(2) - const errdata = JSON.parse(atob(errList[1].url.split('=')[1])) - expect(errdata.d).to.be.an('undefined') - }) - it('should drop data and stack when there is too much', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const tooLong = () => { - let str = '' - for (let i = 0; i < 10000; i++) { - str = str + String.fromCharCode(i % 100) + const returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); + expect(returnStatement).to.be.empty; + }); + + it('should include pixel syncs', () => { + let pixelEnabledOptions = { iframeEnabled: false, pixelEnabled: true }; + const returnStatement = spec.getUserSyncs(pixelEnabledOptions, serverResponse); + console.log(returnStatement) + expect(returnStatement.length).to.equal(2); + expect(returnStatement).to.deep.include.members([{ type: 'image', url: 'http://idprovider1.com' }, + { type: 'image', url: 'http://idprovider2.com' }]); + }); + }); + + describe('prebid 3 upgrade', () => { + const bidRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] } - return str + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', } - const data = {name: 'Oscar Hathenswiotch'} - thrown.stack = tooLong() - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(3) - const errdata = JSON.parse(atob(errList[2].url.split('=')[1])) - expect(errdata.d).to.be.an('undefined') - expect(errdata.s).to.be.an('undefined') + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + it('gets sizes from mediaTypes.banner', () => { + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) + expect(payload.imp[0].banner.w).to.equal(1) + expect(payload.imp[0].banner.h).to.equal(1) }) - it('should drop send a reduced message when other reduction methods fail', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const tooLong = () => { - let str = '' - for (let i = 0; i < 10000; i++) { - str = str + String.fromCharCode(i % 100) - } - return str - } - const data = {name: 'Oscar Hathenswiotch'} - thrown.message = tooLong() - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(4) - const errdata = JSON.parse(atob(errList[3].url.split('=')[1])) - expect(errdata.d).to.be.an('undefined') - expect(errdata.s).to.be.an('undefined') - expect(errdata.m).to.equal('unknown error message') + + it('gets correct site info', () => { + expect(payload.site.page).to.equal('http://example.com/page.html'); + expect(payload.site.domain).to.equal('example.com'); }) }) }) From d50df4670181921e572d395282c6df1554003bcd Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 24 Oct 2019 18:39:10 +0200 Subject: [PATCH 334/436] Add bid adapter for ablida (#4256) * Add ablida adapter * rename category parameter, add documentation --- modules/ablidaBidAdapter.js | 93 +++++++++++++++++++ modules/ablidaBidAdapter.md | 32 +++++++ test/spec/modules/ablidaBidAdapter_spec.js | 102 +++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 modules/ablidaBidAdapter.js create mode 100644 modules/ablidaBidAdapter.md create mode 100644 test/spec/modules/ablidaBidAdapter_spec.js diff --git a/modules/ablidaBidAdapter.js b/modules/ablidaBidAdapter.js new file mode 100644 index 00000000000..33642a1ac9e --- /dev/null +++ b/modules/ablidaBidAdapter.js @@ -0,0 +1,93 @@ +import * as utils from '../src/utils'; +import {config} from '../src/config'; +import {registerBidder} from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = 'ablida'; +const ENDPOINT_URL = 'https://bidder.ablida.net/prebid'; + +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. + * + * @return Array Info describing the request to the server. + * @param validBidRequests + * @param bidderRequest + */ + buildRequests: function (validBidRequests, bidderRequest) { + if (validBidRequests.length === 0) { + return []; + } + return validBidRequests.map(bidRequest => { + const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const size = sizes.split('x'); + const jaySupported = 'atob' in window && 'currentScript' in document; + const device = getDevice(); + const payload = { + placementId: bidRequest.params.placementId, + width: size[0], + height: size[1], + bidId: bidRequest.bidId, + categories: bidRequest.params.categories, + referer: bidderRequest.refererInfo.referer, + jaySupported: jaySupported, + device: device + }; + return { + method: 'POST', + url: ENDPOINT_URL, + data: payload + }; + }); + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param bidRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse, bidRequest) { + const bidResponses = []; + const response = serverResponse.body; + + response.forEach(function(bid) { + bid.ttl = config.getConfig('_bidderTimeout'); + bidResponses.push(bid); + }); + return bidResponses; + }, +}; + +function getDevice() { + const ua = navigator.userAgent; + const topWindow = window.top; + if ((/(ipad|xoom|sch-i800|playbook|silk|tablet|kindle)|(android(?!.*mobi))/i).test(ua)) { + return 'tablet'; + } + if ((/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(ua)) { + return 'connectedtv'; + } + if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Windows\sCE|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/i).test(ua)) { + return 'smartphone'; + } + const width = topWindow.innerWidth || topWindow.document.documentElement.clientWidth || topWindow.document.body.clientWidth; + if (width > 320) { + return 'desktop'; + } + return 'other'; +} + +registerBidder(spec); diff --git a/modules/ablidaBidAdapter.md b/modules/ablidaBidAdapter.md new file mode 100644 index 00000000000..70e6576cd30 --- /dev/null +++ b/modules/ablidaBidAdapter.md @@ -0,0 +1,32 @@ +# Overview + +**Module Name**: Ablida Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: d.kuster@ablida.de + +# Description + +Module that connects to Ablida's bidder for bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'ad-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [ + { + bidder: 'ablida', + params: { + placementId: 'mediumrectangle-demo', + categories: ['automotive', 'news-and-politics'] // optional: categories of page + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/ablidaBidAdapter_spec.js b/test/spec/modules/ablidaBidAdapter_spec.js new file mode 100644 index 00000000000..8e0424aee23 --- /dev/null +++ b/test/spec/modules/ablidaBidAdapter_spec.js @@ -0,0 +1,102 @@ +import {assert, expect} from 'chai'; +import {spec} from 'modules/ablidaBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT_URL = 'https://bidder.ablida.net/prebid'; + +describe('ablidaBidAdapter', function () { + const adapter = newBidder(spec); + describe('isBidRequestValid', function () { + let bid = { + bidder: 'ablida', + params: { + placementId: 123 + }, + adUnitCode: 'adunit-code', + sizes: [ + [300, 250] + ], + bidId: '1234asdf1234', + bidderRequestId: '1234asdf1234asdf', + auctionId: '69e8fef8-5105-4a99-b011-d5669f3bc7f0' + }; + it('should return true where required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + describe('buildRequests', function () { + let bidRequests = [ + { + bidder: 'ablida', + params: { + placementId: 123 + }, + sizes: [ + [300, 250] + ], + adUnitCode: 'adunit-code', + bidId: '23beaa6af6cdde', + bidderRequestId: '14d2939272a26a', + auctionId: '69e8fef8-5105-4a99-b011-d5669f3bc7f0', + } + ]; + + let bidderRequests = { + refererInfo: { + numIframes: 0, + reachedTop: true, + referer: 'http://example.com', + stack: ['http://example.com'] + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequests); + it('sends bid request via POST', function () { + expect(request[0].method).to.equal('POST'); + }); + }); + + describe('interpretResponse', function () { + let bidRequest = { + method: 'POST', + url: ENDPOINT_URL, + data: { + placementId: 'testPlacementId', + width: 300, + height: 200, + bidId: '2b8c4de0116e54', + jaySupported: true, + device: 'desktop', + referer: 'www.example.com' + } + }; + let serverResponse = { + body: [{ + requestId: '2b8c4de0116e54', + cpm: 1.00, + width: 300, + height: 250, + creativeId: '2b8c4de0116e54', + currency: 'EUR', + netRevenue: true, + ttl: 3000, + ad: '' + }] + }; + it('should get the correct bid response', function () { + let expectedResponse = [{ + requestId: '2b8c4de0116e54', + cpm: 1.00, + width: 300, + height: 250, + creativeId: '2b8c4de0116e54', + currency: 'EUR', + netRevenue: true, + ttl: 3000, + ad: '' + }]; + let result = spec.interpretResponse(serverResponse, bidRequest[0]); + expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + }); + }); +}); From 8769781f5430a79c7d6d0a236c595128ade05ed1 Mon Sep 17 00:00:00 2001 From: romanantropov <45817046+romanantropov@users.noreply.github.com> Date: Thu, 24 Oct 2019 20:24:26 +0300 Subject: [PATCH 335/436] AdKernel: added waardex_ak alias (#4290) * added alias Added a new alias * fixing unit test --- modules/adkernelBidAdapter.js | 2 +- test/spec/modules/adkernelBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index a5f8f65634d..c406604b20e 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -23,7 +23,7 @@ const VERSION = '1.3'; export const spec = { code: 'adkernel', - aliases: ['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia'], + aliases: ['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia', 'waardex_ak'], supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bidRequest) { return 'params' in bidRequest && diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index 1f221cd956e..ddb3f3dddf2 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -379,8 +379,8 @@ describe('Adkernel adapter', function () { describe('adapter configuration', () => { it('should have aliases', () => { - expect(spec.aliases).to.have.lengthOf(4); - expect(spec.aliases).to.be.eql(['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia']); + expect(spec.aliases).to.have.lengthOf(5); + expect(spec.aliases).to.be.eql(['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia', 'waardex_ak']); }); }); }); From d3acc446ed0e8f1f993ea8e43abba502ad65849f Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Thu, 24 Oct 2019 15:19:25 -0400 Subject: [PATCH 336/436] Revert "Sovrn adapter updates: schain, digitrust, pixel syncing, and 3.0 upgrades (#4335)" (#4376) This reverts commit 6114a3dba93815dcfb535707d7b4d84f1adb2bc7. --- modules/sovrnBidAdapter.js | 134 +++++----- test/spec/modules/sovrnBidAdapter_spec.js | 286 ++++++++-------------- 2 files changed, 172 insertions(+), 248 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 935bbad79a7..8b08b3ad6be 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,6 +1,8 @@ import * as utils from '../src/utils' import { registerBidder } from '../src/adapters/bidderFactory' import { BANNER } from '../src/mediaTypes' +const errorUrl = 'https://pcb.aws.lijit.com/c' +let errorpxls = [] export const spec = { code: 'sovrn', @@ -22,30 +24,14 @@ export const spec = { */ buildRequests: function(bidReqs, bidderRequest) { try { + const loc = utils.getTopWindowLocation(); let sovrnImps = []; let iv; - let schain; - let digitrust; - utils._each(bidReqs, function (bid) { - if (!digitrust) { - const bidRequestDigitrust = utils.deepAccess(bid, 'userId.digitrustid.data'); - if (bidRequestDigitrust && (!bidRequestDigitrust.privacy || !bidRequestDigitrust.privacy.optout)) { - digitrust = { - id: bidRequestDigitrust.id, - keyv: bidRequestDigitrust.keyv - } - } - } - if (bid.schain) { - schain = schain || bid.schain; - } iv = iv || utils.getBidIdParameter('iv', bid.params); - - let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; - bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]) - bidSizes = bidSizes.filter(size => utils.isArray(size)) - const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) + bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]) + bid.sizes = bid.sizes.filter(size => utils.isArray(size)) + const processedSizes = bid.sizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) sovrnImps.push({ id: bid.bidId, banner: { @@ -57,30 +43,15 @@ export const spec = { bidfloor: utils.getBidIdParameter('bidfloor', bid.params) }); }); - - const page = bidderRequest.refererInfo.referer - // clever trick to get the domain - const el = document.createElement('a'); - el.href = page; - const domain = el.hostname; - const sovrnBidReq = { id: utils.getUniqueIdentifierStr(), imp: sovrnImps, site: { - page, - domain + domain: loc.host, + page: loc.host + loc.pathname + loc.search + loc.hash } }; - if (schain) { - sovrnBidReq.source = { - ext: { - schain - } - }; - } - if (bidderRequest && bidderRequest.gdprConsent) { sovrnBidReq.regs = { ext: { @@ -92,14 +63,7 @@ export const spec = { }}; } - if (digitrust) { - utils.deepSetValue(sovrnBidReq, 'user.ext.digitrust', { - id: digitrust.id, - keyv: digitrust.keyv - }) - } - - let url = `https://ap.lijit.com/rtb/bid?` + + let url = `//ap.lijit.com/rtb/bid?` + `src=$$REPO_AND_VERSION$$`; if (iv) url += `&iv=${iv}`; @@ -110,8 +74,7 @@ export const spec = { options: {contentType: 'text/plain'} } } catch (e) { - console.log('error in build:') - console.log(e) + new LogError(e, {bidReqs, bidderRequest}).append() } }, @@ -146,43 +109,74 @@ export const spec = { } return sovrnBidResponses } catch (e) { - console.log('error in interpret:') - console.log(e) + new LogError(e, {id, seatbid}).append() } }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { try { let tracks = [] - if (serverResponses && serverResponses.length !== 0) { - if (syncOptions.iframeEnabled) { - let iidArr = serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.iid')) - .map(resp => resp.body.ext.iid); - let consentString = ''; - if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { - consentString = gdprConsent.consentString - } - if (iidArr[0]) { - tracks.push({ - type: 'iframe', - url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, - }); - } + if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { + let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) + .map(rsp => { return rsp.body.ext.iid }); + let consentString = ''; + if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + consentString = gdprConsent.consentString } - - if (syncOptions.pixelEnabled) { - serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.sync.pixels')) - .flatMap(resp => resp.body.ext.sync.pixels) - .map(pixel => pixel.url) - .forEach(url => tracks.push({ type: 'image', url })) + if (iidArr[0]) { + tracks.push({ + type: 'iframe', + url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, + }); } } - + if (errorpxls.length && syncOptions.pixelEnabled) { + tracks = tracks.concat(errorpxls) + } return tracks } catch (e) { + if (syncOptions.pixelEnabled) { + return errorpxls + } return [] } }, } +export class LogError { + constructor(e, data) { + utils.logError(e) + this.error = {} + this.error.t = utils.timestamp() + this.error.m = e.message + this.error.s = e.stack + this.error.d = data + this.error.v = $$REPO_AND_VERSION$$ + this.error.u = utils.getTopWindowLocation().href + this.error.ua = navigator.userAgent + } + buildErrorString(obj) { + return errorUrl + '?b=' + btoa(JSON.stringify(obj)) + } + append() { + let errstr = this.buildErrorString(this.error) + if (errstr.length > 2083) { + delete this.error.d + errstr = this.buildErrorString(this.error) + if (errstr.length > 2083) { + delete this.error.s + errstr = this.buildErrorString(this.error) + if (errstr.length > 2083) { + errstr = this.buildErrorString({m: 'unknown error message', t: this.error.t, u: this.error.u}) + } + } + } + let obj = {type: 'image', url: errstr} + errorpxls.push(obj) + } + static getErrPxls() { + return errorpxls + } +} + registerBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index af27e6e74a6..7179ec00bc3 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,8 +1,9 @@ -import {expect} from 'chai'; -import {LogError, spec} from 'modules/sovrnBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; +import { expect } from 'chai'; +import { spec, LogError } from 'modules/sovrnBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { SSL_OP_SINGLE_ECDH_USE } from 'constants'; -const ENDPOINT = `https://ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; +const ENDPOINT = `//ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; describe('sovrnBidAdapter', function() { const adapter = newBidder(spec); @@ -54,12 +55,8 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', - } - }; - const request = spec.buildRequests(bidRequests, bidderRequest); + + const request = spec.buildRequests(bidRequests); it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); @@ -76,7 +73,7 @@ describe('sovrnBidAdapter', function() { expect(payload.imp[0].banner.h).to.equal(1) }) - it('accepts a single array as a size', () => { + it('accepts a single array as a size', function() { const singleSize = [{ 'bidder': 'sovrn', 'params': { @@ -88,13 +85,8 @@ describe('sovrnBidAdapter', function() { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' - }] - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', - } - } - const request = spec.buildRequests(singleSize, bidderRequest) + }]; + const request = spec.buildRequests(singleSize) const payload = JSON.parse(request.data) expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]) expect(payload.imp[0].banner.w).to.equal(1) @@ -117,12 +109,7 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', - } - }; - const request = spec.buildRequests(ivBidRequests, bidderRequest); + const request = spec.buildRequests(ivBidRequests); expect(request.url).to.contain('iv=vet') }); @@ -134,22 +121,20 @@ describe('sovrnBidAdapter', function() { 'auctionId': '1d1a030790a475', 'bidderRequestId': '22edbae2733bf6', 'timeout': 3000, - gdprConsent: { + 'gdprConsent': { consentString: consentString, gdprApplies: true - }, - refererInfo: { - referer: 'http://example.com/page.html', } }; bidderRequest.bids = bidRequests; - const data = JSON.parse(spec.buildRequests(bidRequests, bidderRequest).data); + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); - expect(data.regs.ext.gdpr).to.exist.and.to.be.a('number'); - expect(data.regs.ext.gdpr).to.equal(1); - expect(data.user.ext.consent).to.exist.and.to.be.a('string'); - expect(data.user.ext.consent).to.equal(consentString); + 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', function () { @@ -168,86 +153,10 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', - } - }; - const request = spec.buildRequests(ivBidRequests, bidderRequest); + const request = spec.buildRequests(ivBidRequests); expect(request.data).to.contain('"tagid":"403370"') - }); - - it('should add schain if present', () => { - const schainRequests = [{ - 'bidder': 'sovrn', - 'params': { - 'tagid': 403370 - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250], - [300, 600] - ], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'directseller.com', - 'sid': '00001', - 'rid': 'BidRequest1', - 'hp': 1 - } - ] - } - }].concat(bidRequests); - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', - } - }; - const data = JSON.parse(spec.buildRequests(schainRequests, bidderRequest).data); - - expect(data.source.ext.schain.nodes.length).to.equal(1) - }); - - it('should add digitrust data if present', () => { - const digitrustRequests = [{ - 'bidder': 'sovrn', - 'params': { - 'tagid': 403370 - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250], - [300, 600] - ], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'userId': { - 'digitrustid': { - 'data': { - 'id': 'digitrust-id-123', - 'keyv': 4 - } - } - } - }].concat(bidRequests); - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', - } - }; - const data = JSON.parse(spec.buildRequests(digitrustRequests, bidderRequest).data); - - expect(data.user.ext.digitrust.id).to.equal('digitrust-id-123'); - expect(data.user.ext.digitrust.keyv).to.equal(4); - }); + }) }); describe('interpretResponse', function () { @@ -345,8 +254,8 @@ describe('sovrnBidAdapter', function() { }); describe('getUserSyncs ', () => { - let syncOptions = { iframeEnabled: true, pixelEnabled: false }; - let iframeDisabledSyncOptions = { iframeEnabled: false, pixelEnabled: false }; + let syncOptions = {iframeEnabled: true, pixelEnabled: true}; + let iframeDisabledSyncOptions = {iframeEnabled: false, pixelEnabled: true}; let serverResponse = [ { 'body': { @@ -378,90 +287,111 @@ describe('sovrnBidAdapter', function() { } ], 'ext': { - 'iid': 13487408, - sync: { - pixels: [ - { - url: 'http://idprovider1.com' - }, - { - url: 'http://idprovider2.com' - } - ] - } + 'iid': 13487408 } }, 'headers': {} } ]; - it('should return if iid present on server response & iframe syncs enabled', () => { - const expectedReturnStatement = [ + let expectedReturnStatement = [ { 'type': 'iframe', 'url': '//ap.lijit.com/beacon?informer=13487408&gdpr_consent=', } - ]; - const returnStatement = spec.getUserSyncs(syncOptions, serverResponse); + ] + let returnStatement = spec.getUserSyncs(syncOptions, serverResponse); expect(returnStatement[0]).to.deep.equal(expectedReturnStatement[0]); - }); + }) it('should not return if iid missing on server response', () => { - const returnStatement = spec.getUserSyncs(syncOptions, []); + let returnStatement = spec.getUserSyncs(syncOptions, []) expect(returnStatement).to.be.empty; - }); + }) it('should not return if iframe syncs disabled', () => { - const returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); - expect(returnStatement).to.be.empty; - }); - - it('should include pixel syncs', () => { - let pixelEnabledOptions = { iframeEnabled: false, pixelEnabled: true }; - const returnStatement = spec.getUserSyncs(pixelEnabledOptions, serverResponse); - console.log(returnStatement) - expect(returnStatement.length).to.equal(2); - expect(returnStatement).to.deep.include.members([{ type: 'image', url: 'http://idprovider1.com' }, - { type: 'image', url: 'http://idprovider2.com' }]); - }); - }); - - describe('prebid 3 upgrade', () => { - const bidRequests = [{ - 'bidder': 'sovrn', - 'params': { - 'tagid': '403370' - }, - 'adUnitCode': 'adunit-code', - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600] - ] + let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse) + expect(returnStatement).to.be.empty + }) + }) + describe('LogError', () => { + it('should build and append an error object', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const data = {name: 'Oscar Hathenswiotch'} + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(1) + const errdata = JSON.parse(atob(errList[0].url.split('=')[1])) + expect(errdata.d.name).to.equal('Oscar Hathenswiotch') + }) + it('should drop data when there is too much', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const tooLong = () => { + let str = '' + for (let i = 0; i < 10000; i++) { + str = str + String.fromCharCode(i % 100) } - }, - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' - }]; - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/page.html', + return str } - }; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - it('gets sizes from mediaTypes.banner', () => { - expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) - expect(payload.imp[0].banner.w).to.equal(1) - expect(payload.imp[0].banner.h).to.equal(1) + const data = {name: 'Oscar Hathenswiotch', tooLong: tooLong()} + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(2) + const errdata = JSON.parse(atob(errList[1].url.split('=')[1])) + expect(errdata.d).to.be.an('undefined') }) - - it('gets correct site info', () => { - expect(payload.site.page).to.equal('http://example.com/page.html'); - expect(payload.site.domain).to.equal('example.com'); + it('should drop data and stack when there is too much', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const tooLong = () => { + let str = '' + for (let i = 0; i < 10000; i++) { + str = str + String.fromCharCode(i % 100) + } + return str + } + const data = {name: 'Oscar Hathenswiotch'} + thrown.stack = tooLong() + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(3) + const errdata = JSON.parse(atob(errList[2].url.split('=')[1])) + expect(errdata.d).to.be.an('undefined') + expect(errdata.s).to.be.an('undefined') + }) + it('should drop send a reduced message when other reduction methods fail', () => { + const thrown = { + message: 'message', + stack: 'stack' + } + const tooLong = () => { + let str = '' + for (let i = 0; i < 10000; i++) { + str = str + String.fromCharCode(i % 100) + } + return str + } + const data = {name: 'Oscar Hathenswiotch'} + thrown.message = tooLong() + const err = new LogError(thrown, data) + err.append() + const errList = LogError.getErrPxls() + expect(errList.length).to.equal(4) + const errdata = JSON.parse(atob(errList[3].url.split('=')[1])) + expect(errdata.d).to.be.an('undefined') + expect(errdata.s).to.be.an('undefined') + expect(errdata.m).to.equal('unknown error message') }) }) }) From 2bcde2b233dd0e4478dbabb224d99dcb12de600b Mon Sep 17 00:00:00 2001 From: vrtcal-dev <50931150+vrtcal-dev@users.noreply.github.com> Date: Thu, 24 Oct 2019 15:16:06 -0500 Subject: [PATCH 337/436] Vrtcal Markets Inc. Bid Adapter Addition (#4259) * Added 3 key Vrtcal Adapter files: adapter,markdown,unit tests * Removed unused getUserSyncs;Added mediaTypes.banner.sizes support;Raised test coverage to 85% * lint formatting errors corrected --- modules/vrtcalBidAdapter.js | 88 ++++++++++++++ modules/vrtcalBidAdapter.md | 30 +++++ test/spec/modules/vrtcalBidAdapter_spec.js | 135 +++++++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 modules/vrtcalBidAdapter.js create mode 100644 modules/vrtcalBidAdapter.md create mode 100644 test/spec/modules/vrtcalBidAdapter_spec.js diff --git a/modules/vrtcalBidAdapter.js b/modules/vrtcalBidAdapter.js new file mode 100644 index 00000000000..139f985ed67 --- /dev/null +++ b/modules/vrtcalBidAdapter.js @@ -0,0 +1,88 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; +import {ajax} from '../src/ajax'; + +export const spec = { + code: 'vrtcal', + supportedMediaTypes: [BANNER], + isBidRequestValid: function (bid) { + if (bid.bidId == '' || bid.auctionId == '') { return false; } else { return true; }// No extras params required + }, + buildRequests: function (bidRequests) { + const requests = bidRequests.map(function (bid) { + const params = { + + prebidJS: 1, + prebidAdUnitCode: bid.adUnitCode, + id: bid.bidId, + imp: [{ + id: '1', + banner: { + }, + bidfloor: 0.75 + }], + site: { + id: 'VRTCAL_FILLED', + name: 'VRTCAL_FILLED', + cat: ['VRTCAL_FILLED'], + domain: decodeURIComponent(window.location.href).replace('https://', '').replace('http://', '').split('/')[0] + + }, + device: { + ua: 'VRTCAL_FILLED', + ip: 'VRTCAL_FILLED' + } + }; + + if (typeof (bid.mediaTypes) !== 'undefined' && typeof (bid.mediaTypes.banner) !== 'undefined' && typeof (bid.mediaTypes.banner.sizes) !== 'undefined') { + params.imp[0].banner.w = bid.mediaTypes.banner.sizes[0][0]; + params.imp[0].banner.h = bid.mediaTypes.banner.sizes[0][1]; + } else { + params.imp[0].banner.w = bid.sizes[0][0]; + params.imp[0].banner.h = bid.sizes[0][1]; + } + + return {method: 'POST', url: 'https://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804', data: JSON.stringify(params), options: {withCredentials: false, crossOrigin: true}} + }); + + return requests; + }, + interpretResponse: function (serverResponse, bidRequest) { + if (!serverResponse || !serverResponse.body) { + return []; + } + + const bidResponses = []; + + var response = serverResponse.body; + + if (response) { + const bidResponse = { + requestId: response.id, + cpm: response.seatbid[0].bid[0].price, + width: response.seatbid[0].bid[0].w, + height: response.seatbid[0].bid[0].h, + creativeId: response.seatbid[0].bid[0].crid, + currency: 'USD', + netRevenue: true, + ttl: 900, + ad: response.seatbid[0].bid[0].adm, + nurl: response.seatbid[0].bid[0].nurl + }; + + bidResponses.push(bidResponse); + } + return bidResponses; + }, + onBidWon: function(bid) { + if (!bid.nurl) { return false; } + const winUrl = bid.nurl.replace( + /\$\{AUCTION_PRICE\}/, + bid.cpm + ); + ajax(winUrl, null); + return true; + } +}; + +registerBidder(spec); diff --git a/modules/vrtcalBidAdapter.md b/modules/vrtcalBidAdapter.md new file mode 100644 index 00000000000..8d2809f7d5d --- /dev/null +++ b/modules/vrtcalBidAdapter.md @@ -0,0 +1,30 @@ +# Overview + +Module Name: Vrtcal Bidder Adapter +Module Type: Bidder Adapter +Maintainer: support@vrtcal.com + +# Description + +You can use this adapter to get a bid from vrtcal.com. + + +# Test Parameters +``` + var adUnits = [ + { + code: "vrtcal-test-adunit", + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: "vrtcal" + } + ] + } + ]; +``` +#Vrtcal requires no extra params passed, thus no params struct included diff --git a/test/spec/modules/vrtcalBidAdapter_spec.js b/test/spec/modules/vrtcalBidAdapter_spec.js new file mode 100644 index 00000000000..7b37e393575 --- /dev/null +++ b/test/spec/modules/vrtcalBidAdapter_spec.js @@ -0,0 +1,135 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/vrtcalBidAdapter'; + +describe('Vrtcal Adapter', function () { + let bid = { + bidId: 'bidID0001', + bidder: 'vrtcal', + bidderRequestId: 'brID0001', + auctionId: 'auID0001', + sizes: [[300, 250]], + transactionId: 'tid0001', + adUnitCode: 'vrtcal-test-adunit' + }; + + describe('isBidRequestValid', function () { + it('Should return true when base params as set', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when bid.bidId is blank', function () { + bid.bidId = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + it('Should return false when bid.auctionId is blank', function () { + bid.auctionId = ''; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function () { + let serverRequests = spec.buildRequests([bid]); + + let serverRequest = serverRequests[0]; + + it('Creates a ServerRequest object with method, URL and data', function () { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', function () { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', function () { + expect(serverRequest.url).to.equal('https://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804'); + }); + + it('Returns valid data if array of bids is valid', function () { + let data = JSON.parse(serverRequest.data); + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('prebidJS', 'prebidAdUnitCode', 'id', 'imp', 'site', 'device'); + expect(data.prebidJS).to.not.equal(''); + expect(data.prebidAdUnitCode).to.not.equal(''); + }); + + it('Sets width and height based on existence of bid.mediaTypes.banner', function () { + let data = JSON.parse(serverRequest.data); + if (typeof (bid.mediaTypes) !== 'undefined' && typeof (bid.mediaTypes.banner) !== 'undefined' && typeof (bid.mediaTypes.banner.sizes) !== 'undefined') { + expect(data.imp[0].banner.w).to.equal(bid.mediaTypes.banner.sizes[0][0]); + expect(data.imp[0].banner.h).to.equal(bid.mediaTypes.banner.sizes[0][1]); + } else { + expect(data.imp[0].banner.w).to.equal(bid.sizes[0][0]); + expect(data.imp[0].banner.h).to.equal(bid.sizes[0][1]); + } + }); + + it('Returns empty data if no valid requests are passed', function () { + serverRequests = spec.buildRequests([]); + expect(serverRequests).to.be.an('array').that.is.empty; + }); + }); + + describe('interpretResponse', function () { + let bid = { + bidId: 'bidID0001', + bidder: 'vrtcal', + bidderRequestId: 'brID0001', + auctionId: 'auID0001', + sizes: [[300, 250]], + transactionId: 'tid0001', + adUnitCode: 'vrtcal-test-adunit' + }; + + let serverRequests = spec.buildRequests([bid]); + + let resObject = {body: {id: 'vrtcal-test-id', width: 300, height: 250, seatbid: [{bid: [{price: 3.0, w: 300, h: 250, crid: 'testcrid', adm: 'testad', nurl: 'https://vrtcal.com/faketracker'}]}], currency: 'USD', netRevenue: true, ttl: 900}}; + + let serverResponses = spec.interpretResponse(resObject, serverRequests); + + it('Returns an array of valid server responses if response object is valid', function () { + expect(serverResponses).to.be.an('array').that.is.not.empty; + for (let i = 0; i < serverResponses.length; i++) { + let dataItem = serverResponses[i]; + expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', + 'netRevenue', 'currency', 'nurl'); + 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.nurl).to.be.a('string'); + } + + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + + describe('onBidWon', function () { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'vrtcal', + bidderRequestId: '145e1d6a7837c9', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', + adUnitCode: 'vrtcal-test-adunit' + }; + + let serverRequests = spec.buildRequests([bid]); + let resObject = {body: {id: 'vrtcal-test-id', width: 300, height: 250, seatbid: [{bid: [{price: 3.0, w: 300, h: 250, crid: 'testcrid', adm: 'testad', nurl: 'https://vrtcal.com/faketracker'}]}], currency: 'USD', netRevenue: true, ttl: 900}}; + let serverResponses = spec.interpretResponse(resObject, serverRequests); + let wonbid = serverResponses[0]; + + it('Returns true is nurl is good/not blank', function () { + expect(wonbid.nurl).to.not.equal(''); + expect(spec.onBidWon(wonbid)).to.be.true; + }); + }); +}); From c4ba051dcddda569f8b4cfc3563249d08364a7bc Mon Sep 17 00:00:00 2001 From: Cody Bonney Date: Fri, 25 Oct 2019 07:08:35 -0600 Subject: [PATCH 338/436] Update schain path in ORTB path for spotxBidAdapter (#4377) - Move schain object from request.ext.source.ext.schain to request.source.ext.schain --- modules/spotxBidAdapter.js | 2 +- test/spec/modules/spotxBidAdapter_spec.js | 31 ++++++++++++----------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js index 45a3c925221..cfa308a8670 100644 --- a/modules/spotxBidAdapter.js +++ b/modules/spotxBidAdapter.js @@ -227,7 +227,7 @@ export const spec = { // Add schain object if it is present if (bid && bid.schain) { - requestPayload['ext']['source'] = { + requestPayload['source'] = { ext: { schain: bid.schain } diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js index 6c6a551b7be..d1662e162aa 100644 --- a/test/spec/modules/spotxBidAdapter_spec.js +++ b/test/spec/modules/spotxBidAdapter_spec.js @@ -183,21 +183,7 @@ describe('the spotx adapter', function () { expect(request.data.imp.bidfloor).to.equal(123); expect(request.data.ext).to.deep.equal({ number_of_ads: 2, - wrap_response: 1, - source: { - ext: { - schain: { - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - hp: 1 - } - ] - } - } - } + wrap_response: 1 }); expect(request.data.user.ext).to.deep.equal({ consented_providers_settings: GOOGLE_CONSENT, @@ -209,6 +195,21 @@ describe('the spotx adapter', function () { }], fpc: 'pubcid_1' }) + + expect(request.data.source).to.deep.equal({ + ext: { + schain: { + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1 + } + ] + } + } + }) }); it('should process premarket bids', function() { From 2720a47f8a2540d5f71bcff09bbca2d8ff85756e Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Fri, 25 Oct 2019 17:28:29 +0300 Subject: [PATCH 339/436] Update Grid Bid Adapter (#4379) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter * Update The Grid Media Bidder Adapter to send refererInfo.referer as 'u' parameter in ad request * Hotfix for referrer in Grid Bid Adapter * Grid Bid Adapter: added wrapperType and wrappweVersion to the ad request --- modules/gridBidAdapter.js | 4 +++- test/spec/modules/gridBidAdapter_spec.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index edbf5ed08bd..ac9a7d30429 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -81,7 +81,9 @@ export const spec = { const payload = { auids: auids.join(','), sizes: utils.getKeys(sizeMap).join(','), - r: reqId + r: reqId, + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$' }; if (bidderRequest) { diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index a191d2211f5..36aaddb8b42 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -93,9 +93,11 @@ describe('TheMediaGrid Adapter', function () { expect(payload).to.have.property('auids', '1'); expect(payload).to.have.property('sizes', '300x250,300x600'); expect(payload).to.have.property('r', '22edbae2733bf6'); + expect(payload).to.have.property('wrapperType', 'Prebid_js'); + expect(payload).to.have.property('wrapperVersion', '$prebid.version$'); }); - it('auids must not be duplicated', function () { + it('sizes must not be duplicated', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); From 6f759ae55b98da7eb22102d084aafbf2c213bea7 Mon Sep 17 00:00:00 2001 From: colbertk <50499465+colbertk@users.noreply.github.com> Date: Fri, 25 Oct 2019 10:53:33 -0400 Subject: [PATCH 340/436] TripleLift: Sending schain (#4375) * Add IdentityLink support and fix UnifiedId. It appears we've been looking for UnifiedId userIds on the bidderRequest object, when they are found on bidRequests. This commit fixes that error, and adds support for IdentityLink. * change maintainer email to group * TripleLift: Sending schain (#1) * Sending schain * null -> undefined --- modules/tripleliftBidAdapter.js | 6 ++++ .../spec/modules/tripleliftBidAdapter_spec.js | 28 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 5ed88384b11..d49e4cde480 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -80,6 +80,7 @@ export const tripleliftAdapterSpec = { function _buildPostBody(bidRequests) { let data = {}; + let { schain } = bidRequests[0]; data.imp = bidRequests.map(function(bid, index) { return { id: index, @@ -102,6 +103,11 @@ function _buildPostBody(bidRequests) { }; } + if (schain) { + data.ext = { + schain + } + } return data; } diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 190f463f7a5..12a2f66dde2 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -56,6 +56,20 @@ describe('triplelift adapter', function () { describe('buildRequests', function () { let bidRequests; let bidderRequest; + const schain = { + validation: 'strict', + config: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1, + } + ] + } + }; this.beforeEach(() => { bidRequests = [ @@ -71,6 +85,7 @@ describe('triplelift adapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: {}, + schain, } ]; @@ -220,6 +235,17 @@ describe('triplelift adapter', function () { expect(url).to.match(new RegExp('(?:' + prebid.version + ')')) expect(url).to.match(/(?:referrer)/); }); + it('should return schain when present', function() { + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + const { data: payload } = request; + expect(payload.ext.schain).to.deep.equal(schain); + }); + it('should not create root level ext when schain is not present', function() { + bidRequests[0].schain = undefined; + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + const { data: payload } = request; + expect(payload.ext).to.deep.equal(undefined); + }); }); describe('interpretResponse', function () { @@ -280,7 +306,7 @@ describe('triplelift adapter', function () { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('should return multile responses to support SRA', function () { + it('should return multiple responses to support SRA', function () { let response = { body: { bids: [ From e8448c30f23d4d496782a45100878897140e86f7 Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Fri, 25 Oct 2019 15:42:35 -0400 Subject: [PATCH 341/436] DistrictmDMX: adding support for schain and remove content type to default to prebid selection (#4366) * adding DMX test @97%, two files added one updated * Update districtm_spec.js * Update districtmDMX.js * adding all districtm needed file * remove legacy file * remove typo || 0 in the test method * force default to return a valid width and height * update unit test code for failing test * changed class for an object * remove package-lock.json * change file name for dmx adapter * renamed files * restaure package-lock.json * update to last package-lock state * update gdpr user consent * fix sizes issue * Documentation updates Adding the readme.md info * update file name and update unit testing import file location * current machine state * lint correction * remove variable assigment duplicate --- modules/districtmDMXBidAdapter.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/districtmDMXBidAdapter.js b/modules/districtmDMXBidAdapter.js index 12b7ac16c0c..f69fca919c0 100644 --- a/modules/districtmDMXBidAdapter.js +++ b/modules/districtmDMXBidAdapter.js @@ -60,6 +60,7 @@ export const spec = { }, buildRequests(bidRequest, bidderRequest) { let timeout = config.getConfig('bidderTimeout'); + let schain = null; let dmxRequest = { id: utils.generateUUID(), cur: ['USD'], @@ -80,6 +81,12 @@ export const spec = { dmxRequest.user.ext = {}; dmxRequest.user.ext.consent = bidderRequest.gdprConsent.consentString; } + try { + schain = bidRequest[0].schain; + dmxRequest.source = {}; + dmxRequest.source.ext = {}; + dmxRequest.source.ext.schain = schain || {} + } catch (e) {} let tosendtags = bidRequest.map(dmx => { var obj = {}; obj.id = dmx.bidId; @@ -96,14 +103,11 @@ export const spec = { return obj; }); dmxRequest.imp = tosendtags; + return { method: 'POST', url: DMXURI, data: JSON.stringify(dmxRequest), - options: { - contentType: 'application/json', - withCredentials: true - }, bidderRequest } }, From e221b512e13e37a0ceefbc71dfc43e989203d75b Mon Sep 17 00:00:00 2001 From: bjorn-lw <32431346+bjorn-lw@users.noreply.github.com> Date: Fri, 25 Oct 2019 21:45:38 +0200 Subject: [PATCH 342/436] Support for ID5 + receive meta data (#4352) * Livewrapped bid and analytics adapter * Fixed some tests for browser compatibility * Fixed some tests for browser compatibility * Changed analytics adapter code name * Fix double quote in debug message * modified how gdpr is being passed * Added support for Publisher Common ID Module * Corrections for ttr in analytics * ANalytics updates * Auction start time stamp changed * Detect recovered ad blocked requests Make it possible to pass dynamic parameters to adapter * Collect info on ad units receiving any valid bid * Support for ID5 Pass metadata from adapter * Typo in test + eids on wrong level --- modules/livewrappedBidAdapter.js | 38 +++++++- .../modules/livewrappedBidAdapter_spec.js | 93 ++++++++++++++++++- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js index 1ad18cb15eb..5006a513454 100644 --- a/modules/livewrappedBidAdapter.js +++ b/modules/livewrappedBidAdapter.js @@ -71,7 +71,8 @@ export const spec = { gdprConsent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined, cookieSupport: !utils.isSafariBrowser() && utils.cookiesAreEnabled(), rcv: getAdblockerRecovered(), - adRequests: [...adRequests] + adRequests: [...adRequests], + rtbData: HandleEids(bidRequests) }; const payloadString = JSON.stringify(payload); return { @@ -101,7 +102,8 @@ export const spec = { ttl: ad.ttl, creativeId: ad.creativeId, netRevenue: true, - currency: serverResponse.body.currency + currency: serverResponse.body.currency, + meta: ad.meta }; bidResponses.push(bidResponse); @@ -198,4 +200,36 @@ function getAdblockerRecovered() { } catch (e) {} } +function AddExternalUserId(eids, value, source, atype, rtiPartner) { + if (utils.isStr(value)) { + var eid = { + source, + uids: [{ + id: value, + atype + }] + }; + + if (rtiPartner) { + eid.uids[0] = {ext: {rtiPartner}}; + } + + eids.push(eid); + } +} + +function HandleEids(bidRequests) { + let eids = []; + const bidRequest = bidRequests[0]; + if (bidRequest && bidRequest.userId) { + AddExternalUserId(eids, utils.deepAccess(bidRequest, `userId.pubcid`), 'pubcommon', 1); // Also add this to eids + AddExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id`), 'id5-sync.com', 1); + } + if (eids.length > 0) { + return {user: {ext: {eids}}}; + } + + return undefined; +} + registerBidder(spec); diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index 855eb2ee3f9..6db8bff4c3d 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -577,6 +577,44 @@ describe('Livewrapped adapter tests', function () { }); }); + it('should make use of Id5-Id if available', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + testbidRequest.bids[0].userId = {}; + testbidRequest.bids[0].userId.id5id = 'id5-user-id'; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(data.rtbData.user.ext.eids).to.deep.equal([{ + 'source': 'id5-sync.com', + 'uids': [{ + 'id': 'id5-user-id', + 'atype': 1 + }] + }]); + }); + + it('should make use of publisher common Id if available', function() { + sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); + sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + let testbidRequest = clone(bidderRequest); + delete testbidRequest.bids[0].params.userId; + testbidRequest.bids[0].userId = {}; + testbidRequest.bids[0].userId.pubcid = 'publisher-common-id'; + let result = spec.buildRequests(testbidRequest.bids, testbidRequest); + let data = JSON.parse(result.data); + + expect(data.rtbData.user.ext.eids).to.deep.equal([{ + 'source': 'pubcommon', + 'uids': [{ + 'id': 'publisher-common-id', + 'atype': 1 + }] + }]); + }); + describe('interpretResponse', function () { it('should handle single success response', function() { let lwResponse = { @@ -591,7 +629,8 @@ describe('Livewrapped adapter tests', function () { bidId: '32e50fad901ae89', auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', - ttl: 120 + ttl: 120, + meta: undefined } ], currency: 'USD' @@ -607,7 +646,8 @@ describe('Livewrapped adapter tests', function () { ttl: 120, creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', netRevenue: true, - currency: 'USD' + currency: 'USD', + meta: undefined }]; let bids = spec.interpretResponse({body: lwResponse}); @@ -628,7 +668,8 @@ describe('Livewrapped adapter tests', function () { bidId: '32e50fad901ae89', auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', - ttl: 120 + ttl: 120, + meta: undefined }, { id: '38e5ddf4-3c01-11e8-86a7-0a44794250d4', @@ -640,7 +681,8 @@ describe('Livewrapped adapter tests', function () { bidId: '42e50fad901ae89', auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', creativeId: '62cbd598-2715-4c43-a06f-229fc170f945:427077', - ttl: 120 + ttl: 120, + meta: undefined } ], currency: 'USD' @@ -656,7 +698,8 @@ describe('Livewrapped adapter tests', function () { ttl: 120, creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', netRevenue: true, - currency: 'USD' + currency: 'USD', + meta: undefined }, { requestId: '42e50fad901ae89', bidderCode: 'livewrapped', @@ -667,7 +710,47 @@ describe('Livewrapped adapter tests', function () { ttl: 120, creativeId: '62cbd598-2715-4c43-a06f-229fc170f945:427077', netRevenue: true, + currency: 'USD', + meta: undefined + }]; + + let bids = spec.interpretResponse({body: lwResponse}); + + expect(bids).to.deep.equal(expectedResponse); + }) + + it('should return meta-data', function() { + let lwResponse = { + ads: [ + { + id: '28e5ddf4-3c01-11e8-86a7-0a44794250d4', + callerId: 'site_outsider_0', + tag: 'ad', + width: 300, + height: 250, + cpmBid: 2.565917, + bidId: '32e50fad901ae89', + auctionId: '13e674db-d4d8-4e19-9d28-ff38177db8bf', + creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', + ttl: 120, + meta: {metadata: 'metadata'} + } + ], currency: 'USD' + }; + + let expectedResponse = [{ + requestId: '32e50fad901ae89', + bidderCode: 'livewrapped', + cpm: 2.565917, + width: 300, + height: 250, + ad: 'ad', + ttl: 120, + creativeId: '52cbd598-2715-4c43-a06f-229fc170f945:427077', + netRevenue: true, + currency: 'USD', + meta: {metadata: 'metadata'} }]; let bids = spec.interpretResponse({body: lwResponse}); From d577822d3f5303ee7a433b40c2219829499efdea Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Mon, 28 Oct 2019 13:15:03 -0400 Subject: [PATCH 343/436] Rubicon Adapter: Always make requests using HTTPS (#4380) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * update changed default value of netRevenue to true * Always make bids requests using https * rp_secure and imp.secure should always be 1 --- modules/rubiconBidAdapter.js | 14 +++++--------- test/spec/modules/rubiconBidAdapter_spec.js | 8 ++++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 7885158425b..d07b6731cda 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -5,13 +5,9 @@ import {BANNER, VIDEO} from '../src/mediaTypes'; const DEFAULT_INTEGRATION = 'pbjs_lite'; -function isSecure() { - return location.protocol === 'https:'; -} - -// use protocol relative urls for http or https -export const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.json'; -export const VIDEO_ENDPOINT = '//prebid-server.rubiconproject.com/openrtb2/auction'; +// always use https, regardless of whether or not current page is secure +export const FASTLANE_ENDPOINT = 'https://fastlane.rubiconproject.com/a/api/fastlane.json'; +export const VIDEO_ENDPOINT = 'https://prebid-server.rubiconproject.com/openrtb2/auction'; export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; const DIGITRUST_PROP_NAMES = { @@ -153,7 +149,7 @@ export const spec = { imp: [{ exp: 300, id: bidRequest.adUnitCode, - secure: isSecure() || bidRequest.params.secure ? 1 : 0, + secure: 1, ext: { rubicon: bidRequest.params }, @@ -397,7 +393,7 @@ export const spec = { 'size_id': parsedSizes[0], 'alt_size_ids': parsedSizes.slice(1).join(',') || undefined, 'rp_floor': (params.floor = parseFloat(params.floor)) > 0.01 ? params.floor : 0.01, - 'rp_secure': isSecure() ? '1' : '0', + 'rp_secure': '1', 'tk_flint': `${configIntType || DEFAULT_INTEGRATION}_v$prebid.version$`, 'x_source.tid': bidRequest.transactionId, 'p_screen_res': _getScreenResolution(), diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0390d4598ae..a3e53c68294 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -316,7 +316,7 @@ describe('the rubicon adapter', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); - expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); + expect(request.url).to.equal('https://fastlane.rubiconproject.com/a/api/fastlane.json'); let expectedQuery = { 'account_id': '14062', @@ -454,7 +454,7 @@ describe('the rubicon adapter', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); - expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); + expect(request.url).to.equal('https://fastlane.rubiconproject.com/a/api/fastlane.json'); // test that all values above are both present and correct Object.keys(expectedQuery).forEach(key => { @@ -470,7 +470,7 @@ describe('the rubicon adapter', function () { [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); data = parseQuery(request.data); - expect(request.url).to.equal('//fastlane.rubiconproject.com/a/api/fastlane.json'); + expect(request.url).to.equal('https://fastlane.rubiconproject.com/a/api/fastlane.json'); // test that all values above are both present and correct Object.keys(expectedQuery).forEach(key => { @@ -967,7 +967,7 @@ describe('the rubicon adapter', function () { 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.url).to.equal('https://fastlane.rubiconproject.com/a/api/fastlane.json'); expect(item.data).to.be.a('string'); // 'bidRequest' type must be 'array' if SRA enabled From 5f8bb6393c3518746090a5dd13d472a8af8a2542 Mon Sep 17 00:00:00 2001 From: 7XBID00 <52267720+7XBID00@users.noreply.github.com> Date: Tue, 29 Oct 2019 06:49:19 +0900 Subject: [PATCH 344/436] 7xbid adapter (#4328) * 7xbid adapter * fix error when cli build --- modules/7xbidBidAdapter.js | 157 +++++++++++++++++++++ modules/7xbidBidAdapter.md | 60 ++++++++ test/spec/modules/7xbidBidAdapter_spec.js | 161 ++++++++++++++++++++++ 3 files changed, 378 insertions(+) create mode 100644 modules/7xbidBidAdapter.js create mode 100644 modules/7xbidBidAdapter.md create mode 100644 test/spec/modules/7xbidBidAdapter_spec.js diff --git a/modules/7xbidBidAdapter.js b/modules/7xbidBidAdapter.js new file mode 100644 index 00000000000..ad0eeaaff1a --- /dev/null +++ b/modules/7xbidBidAdapter.js @@ -0,0 +1,157 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = '7xbid'; +const BIDDER_ALIAS = '7xb'; +const ENDPOINT_BANNER = '//bidder.7xbid.com/api/v1/prebid/banner'; +const ENDPOINT_NATIVE = '//bidder.7xbid.com/api/v1/prebid/native'; +const COOKIE_SYNC_URL = '//bidder.7xbid.com/api/v1/cookie/gen'; +const SUPPORTED_MEDIA_TYPES = ['banner', 'native']; +const SUPPORTED_CURRENCIES = ['USD', 'JPY']; +const DEFAULT_CURRENCY = 'JPY'; +const NET_REVENUE = true; + +const _encodeURIComponent = function(a) { + let b = window.encodeURIComponent(a); + b = b.replace(/'/g, '%27'); + return b; +} + +export const _getUrlVars = function(url) { + var hash; + var myJson = {}; + var hashes = url.slice(url.indexOf('?') + 1).split('&'); + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + myJson[hash[0]] = hash[1]; + } + return myJson; +} + +export const spec = { + code: BIDDER_CODE, + aliases: [BIDDER_ALIAS], // short code + supportedMediaTypes: SUPPORTED_MEDIA_TYPES, + isBidRequestValid: function(bid) { + if (!(bid.params.placementId)) { + return false; + } + + if (bid.params.hasOwnProperty('currency') && + SUPPORTED_CURRENCIES.indexOf(bid.params.currency) === -1) { + utils.logInfo('Invalid currency type, we support only JPY and USD!') + return false; + } + + return true; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + let serverRequests = []; + var refererInfo; + if (bidderRequest && bidderRequest.refererInfo) { + refererInfo = bidderRequest.refererInfo; + } + var g = (typeof (geparams) !== 'undefined' && typeof (geparams) == 'object' && geparams) ? geparams : {}; + validBidRequests.forEach((bid, i) => { + let endpoint = ENDPOINT_BANNER + let data = { + 'placementid': bid.params.placementId, + 'cur': bid.params.hasOwnProperty('currency') ? bid.params.currency : DEFAULT_CURRENCY, + 'ua': navigator.userAgent, + 'adtk': _encodeURIComponent(g.lat ? '0' : '1'), + 'loc': utils.getTopWindowUrl(), + 'topframe': (window.parent === window.self) ? 1 : 0, + 'sw': screen && screen.width, + 'sh': screen && screen.height, + 'cb': Math.floor(Math.random() * 99999999999), + 'tpaf': 1, + 'cks': 1, + 'requestid': bid.bidId + }; + + if (bid.hasOwnProperty('nativeParams')) { + endpoint = ENDPOINT_NATIVE + data.tkf = 1 // return url tracker + data.ad_track = '1' + data.apiv = '1.1.0' + } + + if (refererInfo && refererInfo.referer) { + data.referer = refererInfo.referer; + } else { + data.referer = ''; + } + + serverRequests.push({ + method: 'GET', + url: endpoint, + data: utils.parseQueryStringParameters(data) + }) + }) + + return serverRequests; + }, + interpretResponse: function(serverResponse, request) { + const data = _getUrlVars(request.data) + const successBid = serverResponse.body || {}; + let bidResponses = []; + if (successBid.hasOwnProperty(data.placementid)) { + let bid = successBid[data.placementid] + let bidResponse = { + requestId: bid.requestid, + cpm: bid.price, + creativeId: bid.creativeId, + currency: bid.cur, + netRevenue: NET_REVENUE, + ttl: 700 + }; + + if (bid.hasOwnProperty('title')) { // it is native ad response + bidResponse.mediaType = 'native' + bidResponse.native = { + title: bid.title, + body: bid.description, + cta: bid.cta, + sponsoredBy: bid.advertiser, + clickUrl: _encodeURIComponent(bid.landingURL), + impressionTrackers: bid.trackings, + } + if (bid.screenshots) { + bidResponse.native.image = { + url: bid.screenshots.url, + height: bid.screenshots.height, + width: bid.screenshots.width, + } + } + if (bid.icon) { + bidResponse.native.icon = { + url: bid.icon.url, + height: bid.icon.height, + width: bid.icon.width, + } + } + } else { + bidResponse.ad = bid.adm + bidResponse.width = bid.width + bidResponse.height = bid.height + } + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + return [{ + type: 'image', + url: COOKIE_SYNC_URL + }]; + } +} +registerBidder(spec); diff --git a/modules/7xbidBidAdapter.md b/modules/7xbidBidAdapter.md new file mode 100644 index 00000000000..13a448da992 --- /dev/null +++ b/modules/7xbidBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +Module Name: 7xbid Bid Adapter + +Maintainer: 7xbid.com@gmail.com + +# Description + +Module that connects to 7xbid's demand sources + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'test', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [ + { + bidder: '7xbid', + params: { + placementId: 1425292, + currency: 'USD' + + } + } + ] + }, + { + code: 'test', + mediaTypes: { + native: { + title: { + required: true, + len: 80 + }, + image: { + required: true, + sizes: [150, 50] + }, + sponsoredBy: { + required: true + } + } + }, + bids: [ + { + bidder: '7xbid', + params: { + placementId: 1429695, + currency: 'USD' + } + }, + ], + } + ]; +``` \ No newline at end of file diff --git a/test/spec/modules/7xbidBidAdapter_spec.js b/test/spec/modules/7xbidBidAdapter_spec.js new file mode 100644 index 00000000000..4f32e96ce93 --- /dev/null +++ b/test/spec/modules/7xbidBidAdapter_spec.js @@ -0,0 +1,161 @@ +import {expect} from 'chai'; +import {spec, _getUrlVars} from 'modules/7xbidBidAdapter'; +import * as utils from 'src/utils'; +import {config} from 'src/config'; + +const BASE_URI = '//bidder.7xbid.com/api/v1/prebid/banner' +const NATIVE_BASE_URI = '//bidder.7xbid.com/api/v1/prebid/native' + +describe('7xbid adapter', function() { + let bidRequests; + let nativeBidRequests; + + beforeEach(function() { + bidRequests = [ + { + bidder: '7xbid', + params: { + placementId: 1425292, + currency: 'USD' + } + } + ] + + nativeBidRequests = [ + { + bidder: '7xbid', + params: { + placementId: 1429695, + currency: 'USD' + }, + nativeParams: { + title: { + required: true, + len: 80 + }, + image: { + required: true, + sizes: [150, 50] + }, + sponsoredBy: { + required: true + } + } + } + ] + }) + describe('isBidRequestValid', function () { + it('valid bid case', function () { + let validBid = { + bidder: '7xbid', + params: { + placementId: 1425292, + currency: 'USD' + } + } + let isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('invalid bid case: placementId is not passed', function() { + let validBid = { + bidder: '7xbid', + params: { + } + } + let isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }) + + it('invalid bid case: currency is not support', function() { + let validBid = { + bidder: '7xbid', + params: { + placementId: 1108295, + currency: 'AUD' + } + } + let isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }) + }) + + describe('buildRequests', function () { + it('sends bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(BASE_URI); + expect(request.method).to.equal('GET'); + }); + + it('sends native bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(nativeBidRequests)[0]; + expect(request.url).to.equal(NATIVE_BASE_URI); + expect(request.method).to.equal('GET'); + }); + + it('buildRequests function should not modify original bidRequests object', function () { + let originalBidRequests = utils.deepClone(bidRequests); + let request = spec.buildRequests(bidRequests); + expect(bidRequests).to.deep.equal(originalBidRequests); + }); + + it('buildRequests function should not modify original nativeBidRequests object', function () { + let originalBidRequests = utils.deepClone(nativeBidRequests); + let request = spec.buildRequests(nativeBidRequests); + expect(nativeBidRequests).to.deep.equal(originalBidRequests); + }); + + it('Request params check', function() { + let request = spec.buildRequests(bidRequests)[0]; + const data = _getUrlVars(request.data) + expect(parseInt(data.placementid)).to.exist.and.to.equal(bidRequests[0].params.placementId); + expect(data.cur).to.exist.and.to.equal(bidRequests[0].params.currency); + }) + + it('Native request params check', function() { + let request = spec.buildRequests(nativeBidRequests)[0]; + const data = _getUrlVars(request.data) + expect(parseInt(data.placementid)).to.exist.and.to.equal(nativeBidRequests[0].params.placementId); + expect(data.cur).to.exist.and.to.equal(nativeBidRequests[0].params.currency); + }) + }) + + describe('interpretResponse', function () { + let response = { + 1425292: + { + 'creativeId': '', + 'cur': 'USD', + 'price': 0.0920, + 'width': 300, + 'height': 250, + 'requestid': '2e42361a6172bf', + 'adm': '' + } + } + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '2e42361a6172bf', + 'cpm': 0.0920, + 'width': 300, + 'height': 250, + 'netRevenue': true, + 'currency': 'USD', + 'creativeId': '', + 'ttl': 700, + 'ad': '' + } + ]; + let request = spec.buildRequests(bidRequests)[0]; + let result = spec.interpretResponse({body: response}, request); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + expect(result[0].cpm).to.not.equal(null); + expect(result[0].creativeId).to.not.equal(null); + expect(result[0].ad).to.not.equal(null); + expect(result[0].currency).to.equal('USD'); + expect(result[0].netRevenue).to.equal(true); + }); + }) +}) From e9e2b5c6df8e5821e3df0d8acb4aada676625a53 Mon Sep 17 00:00:00 2001 From: thomas-33across <44033452+thomas-33across@users.noreply.github.com> Date: Wed, 30 Oct 2019 01:40:32 +0800 Subject: [PATCH 345/436] - update 33across adapter cookie sync end point (#4345) - update unit test for 33across adapter --- modules/33acrossBidAdapter.js | 4 ++-- test/spec/modules/33acrossBidAdapter_spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index dc075162141..87754bcba03 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -4,7 +4,7 @@ import * as utils from '../src/utils'; const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; -const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; +const SYNC_ENDPOINT = 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb'; const adapterState = {}; @@ -144,7 +144,7 @@ function _createServerRequest(bidRequest, gdprConsent = {}) { } // Sync object will always be of type iframe for TTX -function _createSync({siteId, gdprConsent = {}}) { +function _createSync({siteId = 'zzz000000000003zzz', gdprConsent = {}}) { const ttxSettings = config.getConfig('ttxSettings'); const syncUrl = (ttxSettings && ttxSettings.syncUrl) || SYNC_ENDPOINT; diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index e98b4600d90..5507b9c1cbc 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -579,11 +579,11 @@ describe('33acrossBidAdapter:', function () { syncs = [ { type: 'iframe', - url: 'https://de.tynt.com/deb/v2?m=xch&rt=html&id=id1' + url: 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb&id=id1' }, { type: 'iframe', - url: 'https://de.tynt.com/deb/v2?m=xch&rt=html&id=id2' + url: 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb&id=id2' }, ]; bidRequests = [ From 0400042ececda9dd35502d45323c5c5f6ba1a474 Mon Sep 17 00:00:00 2001 From: Tomas Kovtun Date: Tue, 29 Oct 2019 19:46:54 +0200 Subject: [PATCH 346/436] Adform adapter: add renderer for outstream bids (#4363) --- modules/adformBidAdapter.js | 20 ++++++++++++++++++-- test/spec/modules/adformBidAdapter_spec.js | 9 +++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index a3aef10e41e..0ac083e7e7c 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -1,8 +1,12 @@ 'use strict'; -import {registerBidder} from '../src/adapters/bidderFactory'; +import { registerBidder } from '../src/adapters/bidderFactory'; import { config } from '../src/config'; import { BANNER, VIDEO } from '../src/mediaTypes'; +import { Renderer } from '../src/Renderer'; +import * as utils from '../src/utils'; + +const OUTSTREAM_RENDERER_URL = 'https://s2.adform.net/banners/scripts/video/outstream/render.js'; const BIDDER_CODE = 'adform'; export const spec = { @@ -18,7 +22,7 @@ export const spec = { var request = []; var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], [ 'fd', 1 ], [ 'url', null ], [ 'tid', null ] ]; var bids = JSON.parse(JSON.stringify(validBidRequests)); - var bidder = (bids[0] && bids[0].bidder) || BIDDER_CODE + var bidder = (bids[0] && bids[0].bidder) || BIDDER_CODE; for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; if ((bid.params.priceType === 'net') || (bid.params.pt === 'net')) { @@ -112,6 +116,12 @@ export const spec = { vastXml: response.vast_content, mediaType: type }; + + if (!bid.renderer && utils.deepAccess(bid, 'mediaTypes.video.context') === 'outstream') { + bidObject.renderer = Renderer.install({id: bid.bidId, url: OUTSTREAM_RENDERER_URL}); + bidObject.renderer.setRender(renderer); + } + if (bidRequest.gdpr) { bidObject.gdpr = bidRequest.gdpr.gdpr; bidObject.gdpr_consent = bidRequest.gdpr.gdpr_consent; @@ -121,6 +131,12 @@ export const spec = { } return bidRespones; + function renderer(bid) { + bid.renderer.push(() => { + window.Adform.renderOutstream(bid); + }); + } + function verifySize(adItem, validSizes) { for (var j = 0, k = validSizes.length; j < k; j++) { if (adItem.width == validSizes[j][0] && diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js index f50474ae500..17eef06c603 100644 --- a/test/spec/modules/adformBidAdapter_spec.js +++ b/test/spec/modules/adformBidAdapter_spec.js @@ -258,6 +258,13 @@ describe('Adform adapter', function () { }; }); + it('should set a renderer for an outstream context', function () { + serverResponse.body = [serverResponse.body[3]]; + bidRequest.bids = [bidRequest.bids[6]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + assert.ok(result[0].renderer); + }); + describe('verifySizes', function () { it('should respond with empty response when sizes doesn\'t match', function () { serverResponse.body[0].response = 'banner'; @@ -309,6 +316,7 @@ describe('Adform adapter', function () { let sizes = [[250, 300], [300, 250], [300, 600]]; let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; + let mediaTypes = [{video: {context: 'outstream'}}]; 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 = [ { @@ -388,6 +396,7 @@ describe('Adform adapter', function () { params: params[4], placementCode: placementCode[2], sizes: [], + mediaTypes: mediaTypes[0], transactionId: '5f33781f-9552-7ev3' } ]; From 0ddb185df33fa7d6b005c2748f7c62a954ea9523 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 29 Oct 2019 15:40:21 -0400 Subject: [PATCH 347/436] Prebid 2.38.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e5effb8627..740d6024e2a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.38.0-pre", + "version": "2.38.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 29c2249248ae9d722b618ceb2a386a43ef77a309 Mon Sep 17 00:00:00 2001 From: Eric Harper Date: Tue, 29 Oct 2019 16:08:35 -0400 Subject: [PATCH 348/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 740d6024e2a..01aaa244e1f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.38.0", + "version": "2.39.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 02df81f3e066761f8bfefd9e8ea45d136073ffba Mon Sep 17 00:00:00 2001 From: Olivier Date: Tue, 29 Oct 2019 21:30:25 +0100 Subject: [PATCH 349/436] Adagio: update with external js (#4217) * Add external loader in AdagioBidAdapter * Change adagioAnalyticsAdapter to "endpoint" type * Change _setPredictions for a generic method * Improve AdagioBidAdapter test coverage * Add features detection in Adagio adapter * Fix adagioBidAdapter tests * Add featuresVersion field to bidRequest * Refacto adagio.queue * Expose versions in ADAGIO namespace * Generate a ADAGIO.pageviewId if missing * Move ad-server events tracking to adagioBidAdapter * Store adUnitCodes in ADAGIO namespace * Update documentation Better description of test parameters. * Add internal array to prevent empty pbjs.adUnits * Be sure to access to window.top - does not work in safe-frame env * Add PrintNumber feature * Be sure to compute features on window.top * Bump versions * Add Post-Bid support - ad-server events are listen in current window (instead of window.top) - a new "outerAdUnitElementId" property is set to ADAGIO.pbjsAdUnits array in case of Post-Bid scenario. This property is the 1st parent element id attribute of the iframe in window.top. * Set pagetype param as optional * Add AdThink ad-server support * Improve internal `pbjsAdUnits.sizes` detection Use the adUnit `mediaTypes.banner.sizes` property if exists to build the `ADAGIO.pbjsAdUnits.sizes`. The use of the `sizes` root property is deprecated. * adagioAnalyticsAdapter: add and improve tests * adagioBidAdapter: add and improve tests # Conflicts: # modules/adagioBidAdapter.js # test/spec/modules/adagioBidAdapter_spec.js * adagioBidAdapter: Bump version 1.5 * Adagio: fix import path * PostBid: insure window.top is accessible for specifics functions * Consistency: use Prebid.js utils and fix deprecated * PostBid: do not build a request if in safeframe * Bump version 2.0.0 * Try to fix tests without UA stubing * Try to fix adagioAnalytics failling tests on CI * Consistency: use Prebid loadExternalScript() * Add "adagio" to Prebid.js adloader vendor whitelist * Remove proprietary ad-server listeners * Add RSA validation to adagio external script --- modules/adagioAnalyticsAdapter.js | 52 +- modules/adagioAnalyticsAdapter.md | 2 +- modules/adagioBidAdapter.js | 407 ++++++++++++-- modules/adagioBidAdapter.md | 66 ++- src/adloader.js | 1 + .../modules/adagioAnalyticsAdapter_spec.js | 183 +++++++ test/spec/modules/adagioBidAdapter_spec.js | 496 ++++++++++++++++-- 7 files changed, 1088 insertions(+), 119 deletions(-) create mode 100644 test/spec/modules/adagioAnalyticsAdapter_spec.js diff --git a/modules/adagioAnalyticsAdapter.js b/modules/adagioAnalyticsAdapter.js index 1cdbec829d9..32b9f0d1b0c 100644 --- a/modules/adagioAnalyticsAdapter.js +++ b/modules/adagioAnalyticsAdapter.js @@ -4,17 +4,53 @@ import adapter from '../src/AnalyticsAdapter'; import adapterManager from '../src/adapterManager'; +import CONSTANTS from '../src/constants.json'; +import * as utils from '../src/utils'; -// This config makes Prebid.js call this function on each event: -// `window['AdagioPrebidAnalytics']('on', eventType, args)` -// If it is missing, then Prebid.js will immediately log an error, -// instead of queueing the events until the function appears. -var adagioAdapter = adapter({ - global: 'AdagioPrebidAnalytics', - handler: 'on', - analyticsType: 'bundle' +const emptyUrl = ''; +const analyticsType = 'endpoint'; +const events = Object.keys(CONSTANTS.EVENTS).map(key => CONSTANTS.EVENTS[key]); +const VERSION = '2.0.0'; + +const adagioEnqueue = function adagioEnqueue(action, data) { + utils.getWindowTop().ADAGIO.queue.push({ action, data, ts: Date.now() }); +} + +function canAccessTopWindow() { + try { + if (utils.getWindowTop().location.href) { + return true; + } + } catch (error) { + return false; + } +} + +let adagioAdapter = Object.assign(adapter({ emptyUrl, analyticsType }), { + track: function({ eventType, args }) { + if (typeof args !== 'undefined' && events.indexOf(eventType) !== -1) { + adagioEnqueue('pb-analytics-event', { eventName: eventType, args }); + } + } }); +adagioAdapter.originEnableAnalytics = adagioAdapter.enableAnalytics; + +adagioAdapter.enableAnalytics = config => { + if (!canAccessTopWindow()) { + return; + } + + const w = utils.getWindowTop(); + + w.ADAGIO = w.ADAGIO || {}; + w.ADAGIO.queue = w.ADAGIO.queue || []; + w.ADAGIO.versions = w.ADAGIO.versions || {}; + w.ADAGIO.versions.adagioAnalyticsAdapter = VERSION; + + adagioAdapter.originEnableAnalytics(config); +} + adapterManager.registerAnalyticsAdapter({ adapter: adagioAdapter, code: 'adagio' diff --git a/modules/adagioAnalyticsAdapter.md b/modules/adagioAnalyticsAdapter.md index 5734bc85b2a..312a26ea8da 100644 --- a/modules/adagioAnalyticsAdapter.md +++ b/modules/adagioAnalyticsAdapter.md @@ -1,7 +1,7 @@ # Overview Module Name: Adagio Analytics Adapter -Module Type: Adagio Adapter +Module Type: Analytics Adapter Maintainer: dev@adagio.io # Description diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index 8f6e59b0633..76614e52bc5 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -1,36 +1,232 @@ import find from 'core-js/library/fn/array/find'; import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import { loadExternalScript } from '../src/adloader' +import JSEncrypt from 'jsencrypt/bin/jsencrypt'; +import sha256 from 'crypto-js/sha256'; const BIDDER_CODE = 'adagio'; -const VERSION = '1.0.0'; +const VERSION = '2.0.0'; +const FEATURES_VERSION = '1'; const ENDPOINT = 'https://mp.4dex.io/prebid'; const SUPPORTED_MEDIA_TYPES = ['banner']; +const ADAGIO_TAG_URL = '//script.4dex.io/localstore.js'; +const ADAGIO_LOCALSTORAGE_KEY = 'adagioScript'; -/** - * Based on https://github.com/ua-parser/uap-cpp/blob/master/UaParser.cpp#L331, with the following updates: - * - replaced `mobile` by `mobi` in the table regexp, so Opera Mobile on phones is not detected as a tablet. - */ -function _getDeviceType() { - let ua = navigator.userAgent; +export const ADAGIO_PUBKEY = `-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9el0+OEn6fvEh1RdVHQu4cnT0 +jFSzIbGJJyg3cKqvtE6A0iaz9PkIdJIvSSSNrmJv+lRGKPEyRA/VnzJIieL39Ngl +t0b0lsHN+W4n9kitS/DZ/xnxWK/9vxhv0ZtL1LL/rwR5Mup7rmJbNtDoNBw4TIGj +pV6EP3MTLosuUEpLaQIDAQAB +-----END PUBLIC KEY-----`; + +export function getAdagioScript() { + try { + const w = utils.getWindowTop(); + const ls = w.localStorage.getItem(ADAGIO_LOCALSTORAGE_KEY); + + if (!ls) { + utils.logWarn('Adagio Script not found'); + return; + } + + const hashRgx = /^(\/\/ hash: (.+)\n)(.+\n)$/; - // Tablets must be checked before phones. - if ((/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i).test(ua)) { - return 5; // "tablet" + if (!hashRgx.test(ls)) { + utils.logWarn('No hash found in Adagio script'); + w.localStorage.removeItem(ADAGIO_LOCALSTORAGE_KEY); + } else { + const r = ls.match(hashRgx); + const hash = r[2]; + const content = r[3]; + + var jsEncrypt = new JSEncrypt(); + jsEncrypt.setPublicKey(ADAGIO_PUBKEY); + + if (jsEncrypt.verify(content, hash, sha256)) { + utils.logInfo('Start Adagio script'); + Function(ls)(); // eslint-disable-line no-new-func + } else { + utils.logWarn('Invalid Adagio script found'); + w.localStorage.removeItem(ADAGIO_LOCALSTORAGE_KEY); + } + } + } catch (err) { + // } - if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/).test(ua)) { - return 4; // "phone" +} + +function canAccessTopWindow() { + try { + if (utils.getWindowTop().location.href) { + return true; + } + } catch (error) { + return false; } - // Consider that all other devices are personal computers - return 2; +} + +function initAdagio() { + const w = utils.getWindowTop(); + + w.ADAGIO = w.ADAGIO || {}; + w.ADAGIO.queue = w.ADAGIO.queue || []; + w.ADAGIO.versions = w.ADAGIO.versions || {}; + w.ADAGIO.versions.adagioBidderAdapter = VERSION; + + getAdagioScript(); + + loadExternalScript(ADAGIO_TAG_URL, BIDDER_CODE) +} + +if (canAccessTopWindow()) { + initAdagio(); +} + +const _features = { + getPrintNumber: function(adUnitCode) { + const adagioAdUnit = _getOrAddAdagioAdUnit(adUnitCode); + return adagioAdUnit.printNumber || 1; + }, + + getPageDimensions: function() { + const viewportDims = _features.getViewPortDimensions().split('x'); + const w = utils.getWindowTop(); + const body = w.document.body; + const html = w.document.documentElement; + const pageHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight); + + return viewportDims[0] + 'x' + pageHeight; + }, + + getViewPortDimensions: function() { + let viewPortWidth; + let viewPortHeight; + const w = utils.getWindowTop(); + const d = w.document; + + if (w.innerWidth) { + viewPortWidth = w.innerWidth; + viewPortHeight = w.innerHeight; + } else { + viewPortWidth = d.getElementsByTagName('body')[0].clientWidth; + viewPortHeight = d.getElementsByTagName('body')[0].clientHeight; + } + + return viewPortWidth + 'x' + viewPortHeight; + }, + + isDomLoading: function() { + const w = utils.getWindowTop(); + let performance = w.performance || w.msPerformance || w.webkitPerformance || w.mozPerformance; + let domLoading = -1; + + if (performance && performance.timing && performance.timing.navigationStart > 0) { + const val = performance.timing.domLoading - performance.timing.navigationStart; + if (val > 0) domLoading = val; + } + return domLoading; + }, + + getSlotPosition: function(element) { + const w = utils.getWindowTop(); + const d = w.document; + const el = element; + + let box = el.getBoundingClientRect(); + const docEl = d.documentElement; + const body = d.body; + const clientTop = d.clientTop || body.clientTop || 0; + const clientLeft = d.clientLeft || body.clientLeft || 0; + const scrollTop = w.pageYOffset || docEl.scrollTop || body.scrollTop; + const scrollLeft = w.pageXOffset || docEl.scrollLeft || body.scrollLeft; + + const elComputedStyle = w.getComputedStyle(el, null); + const elComputedDisplay = elComputedStyle.display || 'block'; + const mustDisplayElement = elComputedDisplay === 'none'; + + if (mustDisplayElement) { + el.style = el.style || {}; + el.style.display = 'block'; + box = el.getBoundingClientRect(); + el.style.display = elComputedDisplay; + } + + const position = { + x: Math.round(box.left + scrollLeft - clientLeft), + y: Math.round(box.top + scrollTop - clientTop) + }; + + return position.x + 'x' + position.y; + }, + + getTimestamp: function() { + return Math.floor(new Date().getTime() / 1000) - new Date().getTimezoneOffset() * 60; + }, + + getDevice: function() { + if (!canAccessTopWindow()) return false; + const w = utils.getWindowTop(); + const ua = w.navigator.userAgent; + + if ((/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i).test(ua)) { + return 5; // "tablet" + } + if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/).test(ua)) { + return 4; // "phone" + } + return 2; // personal computers + }, + + getBrowser: function() { + const w = utils.getWindowTop(); + const ua = w.navigator.userAgent; + const uaLowerCase = ua.toLowerCase(); + return /Edge\/\d./i.test(ua) ? 'edge' : uaLowerCase.indexOf('chrome') > 0 ? 'chrome' : uaLowerCase.indexOf('firefox') > 0 ? 'firefox' : uaLowerCase.indexOf('safari') > 0 ? 'safari' : uaLowerCase.indexOf('opera') > 0 ? 'opera' : uaLowerCase.indexOf('msie') > 0 || w.MSStream ? 'ie' : 'unknow'; + }, + + getOS: function() { + const w = window.top; + const ua = w.navigator.userAgent; + const uaLowerCase = ua.toLowerCase(); + return uaLowerCase.indexOf('linux') > 0 ? 'linux' : uaLowerCase.indexOf('mac') > 0 ? 'mac' : uaLowerCase.indexOf('win') > 0 ? 'windows' : ''; + } +} + +function _pushInAdagioQueue(ob) { + if (!canAccessTopWindow()) return; + const w = utils.getWindowTop(); + w.ADAGIO.queue.push(ob); }; +function _getOrAddAdagioAdUnit(adUnitCode) { + const w = utils.getWindowTop(); + if (w.ADAGIO.adUnits[adUnitCode]) { + return w.ADAGIO.adUnits[adUnitCode] + } + return w.ADAGIO.adUnits[adUnitCode] = {}; +} + +function _computePrintNumber(adUnitCode) { + let printNumber = 1; + const w = utils.getWindowTop(); + if ( + w.ADAGIO && + w.ADAGIO.adUnits && w.ADAGIO.adUnits[adUnitCode] && + w.ADAGIO.adUnits[adUnitCode].pageviewId === _getPageviewId() && + w.ADAGIO.adUnits[adUnitCode].printNumber + ) { + printNumber = parseInt(w.ADAGIO.adUnits[adUnitCode].printNumber, 10) + 1; + } + return printNumber; +} + function _getDevice() { const language = navigator.language ? 'language' : 'userLanguage'; return { userAgent: navigator.userAgent, language: navigator[language], - deviceType: _getDeviceType(), + deviceType: _features.getDevice(), dnt: utils.getDNT() ? 1 : 0, geo: {}, js: 1 @@ -38,36 +234,91 @@ function _getDevice() { }; function _getSite() { - const topLocation = utils.getTopWindowLocation(); + const w = utils.getWindowTop(); return { - domain: topLocation.hostname, - page: topLocation.href, - referrer: utils.getTopWindowReferrer() + domain: w.location.hostname, + page: w.location.href, + referrer: w.document.referrer || '' }; }; function _getPageviewId() { - return (!window.top.ADAGIO || !window.top.ADAGIO.pageviewId) ? '_' : window.top.ADAGIO.pageviewId; + if (!canAccessTopWindow()) return false; + const w = utils.getWindowTop(); + w.ADAGIO.pageviewId = w.ADAGIO.pageviewId || utils.generateUUID(); + return w.ADAGIO.pageviewId; }; +function _getElementFromTopWindow(element, currentWindow) { + if (utils.getWindowTop() === currentWindow) { + if (!element.getAttribute('id')) { + element.setAttribute('id', `adg-${utils.getUniqueIdentifierStr()}`); + } + return element; + } else { + const frame = currentWindow.frameElement; + return _getElementFromTopWindow(frame, currentWindow.parent); + } +} + +/** + * Returns all features for a specific adUnit element + * + * @param {Object} bidRequest + * @returns {Object} features for an element (see specs) + */ function _getFeatures(bidRequest) { - if (!window.top._ADAGIO || !window.top._ADAGIO.features) { - return {}; + if (!canAccessTopWindow()) return; + const w = utils.getWindowTop(); + const adUnitElementId = bidRequest.params.adUnitElementId; + const adUnitCode = bidRequest.adUnitCode; + + let element = window.document.getElementById(adUnitElementId); + + if (bidRequest.params.postBid === true) { + element = _getElementFromTopWindow(element, window); + w.ADAGIO.pbjsAdUnits.map((adUnit) => { + if (adUnit.code === adUnitCode) { + const outerElementId = element.getAttribute('id'); + adUnit.outerAdUnitElementId = outerElementId; + bidRequest.params.outerAdUnitElementId = outerElementId; + } + }); + } else { + element = w.document.getElementById(adUnitElementId); } - const rawFeatures = window.top._ADAGIO.features.getFeatures( - document.getElementById(bidRequest.adUnitCode), - function(features) { - return { - site_id: bidRequest.params.siteId, - placement: bidRequest.params.placementId, - pagetype: bidRequest.params.pagetypeId, - categories: bidRequest.params.categories - }; - } - ); - return rawFeatures; -} + let features = {}; + if (element) { + features = Object.assign({}, { + print_number: _features.getPrintNumber(bidRequest.adUnitCode).toString(), + page_dimensions: _features.getPageDimensions().toString(), + viewport_dimensions: _features.getViewPortDimensions().toString(), + dom_loading: _features.isDomLoading().toString(), + // layout: features.getLayout().toString(), + adunit_position: _features.getSlotPosition(element).toString(), + user_timestamp: _features.getTimestamp().toString(), + device: _features.getDevice().toString(), + url: w.location.origin + w.location.pathname, + browser: _features.getBrowser(), + os: _features.getOS() + }) + } + + const adUnitFeature = {}; + adUnitFeature[adUnitElementId] = { + features: features, + version: FEATURES_VERSION + }; + + _pushInAdagioQueue({ + action: 'features', + ts: Date.now(), + data: adUnitFeature + }); + + return features; +}; function _getGdprConsent(bidderRequest) { const consent = {}; @@ -91,45 +342,77 @@ export const spec = { supportedMediaType: SUPPORTED_MEDIA_TYPES, isBidRequestValid: function(bid) { - return !!(bid.params.siteId && bid.params.placementId); + const { adUnitCode, auctionId, sizes, bidder, params, mediaTypes } = bid; + const { organizationId, site, placement, adUnitElementId } = bid.params; + let isValid = false; + + if (canAccessTopWindow()) { + const w = utils.getWindowTop(); + w.ADAGIO = w.ADAGIO || {}; + w.ADAGIO.adUnits = w.ADAGIO.adUnits || {}; + w.ADAGIO.pbjsAdUnits = w.ADAGIO.pbjsAdUnits || []; + isValid = !!(organizationId && site && placement && adUnitElementId && document.getElementById(adUnitElementId) !== null); + const tempAdUnits = w.ADAGIO.pbjsAdUnits.filter((adUnit) => adUnit.code !== adUnitCode); + tempAdUnits.push({ + code: adUnitCode, + sizes: (mediaTypes && mediaTypes.banner && Array.isArray(mediaTypes.banner.sizes)) ? mediaTypes.banner.sizes : sizes, + bids: [{ + bidder, + params + }] + }); + w.ADAGIO.pbjsAdUnits = tempAdUnits; + + if (isValid === true) { + let printNumber = _computePrintNumber(adUnitCode); + w.ADAGIO.adUnits[adUnitCode] = { + auctionId: auctionId, + pageviewId: _getPageviewId(), + printNumber + }; + } + } + + return isValid; }, buildRequests: function(validBidRequests, bidderRequest) { + // AdagioBidAdapter works when window.top can be reached only + if (!bidderRequest.refererInfo.reachedTop) return []; + const secure = (location.protocol === 'https:') ? 1 : 0; const device = _getDevice(); const site = _getSite(); const pageviewId = _getPageviewId(); const gdprConsent = _getGdprConsent(bidderRequest); const adUnits = utils._map(validBidRequests, (bidRequest) => { - bidRequest.params.features = _getFeatures(bidRequest); - const categories = bidRequest.params.categories; - if (typeof categories !== 'undefined' && !Array.isArray(categories)) { - bidRequest.params.categories = [categories]; - } + bidRequest.features = _getFeatures(bidRequest); return bidRequest; }); // Regroug ad units by siteId const groupedAdUnits = adUnits.reduce((groupedAdUnits, adUnit) => { - (groupedAdUnits[adUnit.params.siteId] = groupedAdUnits[adUnit.params.siteId] || []).push(adUnit); + (groupedAdUnits[adUnit.params.organizationId] = groupedAdUnits[adUnit.params.organizationId] || []).push(adUnit); return groupedAdUnits; }, {}); // Build one request per siteId - const requests = utils._map(Object.keys(groupedAdUnits), (siteId) => { + const requests = utils._map(Object.keys(groupedAdUnits), (organizationId) => { return { method: 'POST', url: ENDPOINT, data: { id: utils.generateUUID(), + organizationId: organizationId, secure: secure, device: device, site: site, - siteId: siteId, pageviewId: pageviewId, - adUnits: groupedAdUnits[siteId], + adUnits: groupedAdUnits[organizationId], gdpr: gdprConsent, - adapterVersion: VERSION + prebidVersion: '$prebid.version$', + adapterVersion: VERSION, + featuresVersion: FEATURES_VERSION }, options: { contentType: 'application/json' @@ -145,15 +428,27 @@ export const spec = { try { const response = serverResponse.body; if (response) { - response.bids.forEach(bidObj => { - const bidReq = (find(bidRequest.data.adUnits, bid => bid.bidId === bidObj.requestId)); - if (bidReq) { - bidObj.placementId = bidReq.params.placementId; - bidObj.pagetypeId = bidReq.params.pagetypeId; - bidObj.categories = (bidReq.params.features && bidReq.params.features.categories) ? bidReq.params.features.categories : []; - } - bidResponses.push(bidObj); - }); + if (response.data) { + _pushInAdagioQueue({ + action: 'ssp-data', + ts: Date.now(), + data: response.data + }); + } + if (response.bids) { + response.bids.forEach(bidObj => { + const bidReq = (find(bidRequest.data.adUnits, bid => bid.bidId === bidObj.requestId)); + if (bidReq) { + bidObj.site = bidReq.params.site; + bidObj.placement = bidReq.params.placement; + bidObj.pagetype = bidReq.params.pagetype; + bidObj.category = bidReq.params.category; + bidObj.subcategory = bidReq.params.subcategory; + bidObj.environment = bidReq.params.environment; + } + bidResponses.push(bidObj); + }); + } } } catch (err) { utils.logError(err); diff --git a/modules/adagioBidAdapter.md b/modules/adagioBidAdapter.md index ff33b035e5f..5dc8aa3d80c 100644 --- a/modules/adagioBidAdapter.md +++ b/modules/adagioBidAdapter.md @@ -12,21 +12,33 @@ Connects to Adagio demand source to fetch bids. ```javascript var adUnits = [ + { + code: 'dfp_banniere_atf', + sizes: [[300, 250], [300, 600]], + bids: [ { - code: 'ad-unit_code', - sizes: [[300, 250], [300, 600]], - bids: [ - { - bidder: 'adagio', // Required - params: { - siteId: '0', // Required - Site ID from Adagio. - placementId: '4', // Required - Placement ID from Adagio. Refers to the placement of an ad unit in a page. - pagetypeId: '343', // Required - Page type ID from Adagio. - categories: ['IAB12', 'IAB12-2'], // IAB categories of the page. - } - } - ] - } + bidder: 'adagio', // Required + params: { + organizationId: '0', // Required - Organization ID provided by Adagio. + site: 'news-of-the-day', // Required - Site Name provided by Adagio. + adUnitElementId: 'dfp_banniere_atf', // Required - AdUnit element id. Refers to the adunit id in a page. Usually equals to the adunit code above. + + // The following params are limited to 30 characters, + // and can only contain the following characters: + // - alphanumeric (A-Z+a-z+0-9, case-insensitive) + // - dashes `-` + // - underscores `_` + // Also, each param can have at most 50 unique active values (case-insensitive). + environment: 'mobile', // Required. Environment where the page is displayed. + placement: 'ban_atf', // Required. Refers to the placement of an adunit in a page. Must not contain any information about the type of device. Other example: `mpu_btf'. + pagetype: 'article', // Required. The pagetype describes what kind of content will be present in the page. + category: 'sport', // Recommended. Category of the content displayed in the page. + subcategory: 'handball', // Optional. Subcategory of the content displayed in the page. + postBid: false // Optional. Use it in case of Post-bid integration only. + } + } + ] + } ]; pbjs.addAdUnits(adUnits); @@ -35,22 +47,40 @@ Connects to Adagio demand source to fetch bids. adagio: { alwaysUseBid: true, adserverTargeting: [ + { + key: "site", + val: function (bidResponse) { + return bidResponse.site; + } + }, + { + key: "environment", + val: function (bidResponse) { + return bidResponse.environment; + } + }, { key: "placement", val: function (bidResponse) { - return bidResponse.placementId; + return bidResponse.placement; } }, { key: "pagetype", val: function (bidResponse) { - return bidResponse.pagetypeId; + return bidResponse.pagetype; + } + }, + { + key: "category", + val: function (bidResponse) { + return bidResponse.category; } }, { - key: "categories", + key: "subcategory", val: function (bidResponse) { - return bidResponse.categories.join(","); + return bidResponse.subcategory; } } ] diff --git a/src/adloader.js b/src/adloader.js index b422c802393..c45dacd8af0 100644 --- a/src/adloader.js +++ b/src/adloader.js @@ -4,6 +4,7 @@ import * as utils from './utils'; const _requestCache = {}; const _vendorWhitelist = [ 'criteo', + 'adagio' ] /** diff --git a/test/spec/modules/adagioAnalyticsAdapter_spec.js b/test/spec/modules/adagioAnalyticsAdapter_spec.js new file mode 100644 index 00000000000..8c07b86f8e9 --- /dev/null +++ b/test/spec/modules/adagioAnalyticsAdapter_spec.js @@ -0,0 +1,183 @@ +import adagioAnalyticsAdapter from 'modules/adagioAnalyticsAdapter'; +import { expect } from 'chai'; +import * as utils from 'src/utils'; + +let adapterManager = require('src/adapterManager').default; +let events = require('src/events'); +let constants = require('src/constants.json'); + +describe('adagio analytics adapter', () => { + let xhr; + let requests; + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox(); + + xhr = sandbox.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + sandbox.stub(events, 'getEvents').returns([]); + + adapterManager.registerAnalyticsAdapter({ + code: 'adagio', + adapter: adagioAnalyticsAdapter + }); + }); + + afterEach(() => { + sandbox.restore(); + }); + + describe('track', () => { + beforeEach(() => { + adapterManager.enableAnalytics({ + provider: 'adagio' + }); + }); + + afterEach(() => { + adagioAnalyticsAdapter.disableAnalytics(); + }); + + it('builds and sends auction data', () => { + const w = utils.getWindowTop(); + + let bidRequest = { + bids: [{ + adUnitCode: 'div-1', + params: { + features: { + siteId: '2', + placement: 'pave_top', + pagetype: 'article', + category: 'IAB12,IAB12-2', + device: '2', + } + } + }, { + adUnitCode: 'div-2', + params: { + features: { + siteId: '2', + placement: 'ban_top', + pagetype: 'article', + category: 'IAB12,IAB12-2', + device: '2', + } + }, + }], + }; + let bidResponse = { + bidderCode: 'adagio', + width: 300, + height: 250, + statusMessage: 'Bid available', + cpm: 6.2189757658226075, + currency: '', + netRevenue: false, + adUnitCode: 'div-1', + timeToRespond: 132, + }; + + // Step 1: Send bid requested event + events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + // Step 2: Send bid response event + events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + // Step 3: Send auction end event + events.emit(constants.EVENTS.AUCTION_END, {}); + + expect(w.ADAGIO.queue).length(3); + + let o = w.ADAGIO.queue.shift(); + expect(o).to.not.be.undefined; + expect(o.action).to.equal('pb-analytics-event'); + expect(o.ts).to.not.be.undefined; + expect(o.data).to.not.be.undefined; + expect(o.data).to.deep.equal({eventName: constants.EVENTS.BID_REQUESTED, args: bidRequest}); + + o = w.ADAGIO.queue.shift(); + expect(o).to.not.be.undefined; + expect(o.action).to.equal('pb-analytics-event'); + expect(o.ts).to.not.be.undefined; + expect(o.data).to.not.be.undefined; + expect(o.data).to.deep.equal({eventName: constants.EVENTS.BID_RESPONSE, args: bidResponse}); + + o = w.ADAGIO.queue.shift(); + expect(o).to.not.be.undefined; + expect(o.action).to.equal('pb-analytics-event'); + expect(o.ts).to.not.be.undefined; + expect(o.data).to.not.be.undefined; + expect(o.data).to.deep.equal({eventName: constants.EVENTS.AUCTION_END, args: {}}); + }); + }); + + describe('no track', () => { + beforeEach(() => { + sandbox.stub(utils, 'getWindowTop').throws(); + + adapterManager.enableAnalytics({ + provider: 'adagio' + }); + }); + + afterEach(() => { + adagioAnalyticsAdapter.disableAnalytics(); + sandbox.restore(); + }); + + it('builds and sends auction data', () => { + let bidRequest = { + bids: [{ + adUnitCode: 'div-1', + params: { + features: { + siteId: '2', + placement: 'pave_top', + pagetype: 'article', + category: 'IAB12,IAB12-2', + device: '2', + } + } + }, { + adUnitCode: 'div-2', + params: { + features: { + siteId: '2', + placement: 'ban_top', + pagetype: 'article', + category: 'IAB12,IAB12-2', + device: '2', + } + }, + }], + }; + let bidResponse = { + bidderCode: 'adagio', + width: 300, + height: 250, + statusMessage: 'Bid available', + cpm: 6.2189757658226075, + currency: '', + netRevenue: false, + adUnitCode: 'div-1', + timeToRespond: 132, + }; + + // Step 1: Send bid requested event + events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + // Step 2: Send bid response event + events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + // Step 3: Send auction end event + events.emit(constants.EVENTS.AUCTION_END, {}); + + utils.getWindowTop.restore(); + + expect(utils.getWindowTop().ADAGIO.queue).length(0); + }); + }); +}); diff --git a/test/spec/modules/adagioBidAdapter_spec.js b/test/spec/modules/adagioBidAdapter_spec.js index 7437b45b6c1..6c804418d03 100644 --- a/test/spec/modules/adagioBidAdapter_spec.js +++ b/test/spec/modules/adagioBidAdapter_spec.js @@ -1,10 +1,22 @@ import { expect } from 'chai'; +import { getAdagioScript, spec } from 'modules/adagioBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -import { spec } from 'modules/adagioBidAdapter'; +import * as utils from 'src/utils'; describe('adagioAdapter', () => { + let utilsMock; const adapter = newBidder(spec); const ENDPOINT = 'https://mp.4dex.io/prebid'; + const VERSION = '2.0.0'; + + beforeEach(function() { + localStorage.removeItem('adagioScript'); + utilsMock = sinon.mock(utils); + }); + + afterEach(function() { + utilsMock.restore(); + }); describe('inherited functions', () => { it('exists and is a function', () => { @@ -13,12 +25,40 @@ describe('adagioAdapter', () => { }); describe('isBidRequestValid', () => { + let sandbox; + beforeEach(function () { + sandbox = sinon.sandbox.create(); + let element = { + x: 0, + y: 0, + width: 200, + height: 300, + getBoundingClientRect: () => { + return { + width: element.width, + height: element.height, + left: element.x, + top: element.y, + right: element.x + element.width, + bottom: element.y + element.height + }; + } + }; + sandbox.stub(document, 'getElementById').withArgs('banner-atf').returns(element); + }); + + afterEach(function () { + sandbox.restore(); + }); + let bid = { 'bidder': 'adagio', 'params': { - siteId: '123', - placementId: 4, - categories: ['IAB12', 'IAB12-2'] + organizationId: '0', + placement: 'PAVE_ATF', + site: 'SITE-NAME', + pagetype: 'ARTICLE', + adUnitElementId: 'banner-atf' }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250], [300, 600]], @@ -27,33 +67,168 @@ describe('adagioAdapter', () => { 'auctionId': 'lel4fhp239i9km', }; + let bidWithMediaTypes = { + 'bidder': 'adagio', + 'params': { + organizationId: '0', + placement: 'PAVE_ATF', + site: 'SITE-NAME', + pagetype: 'ARTICLE', + adUnitElementId: 'banner-atf' + }, + 'adUnitCode': 'adunit-code-2', + 'mediaTypes': { + banner: { + sizes: [[300, 250]], + } + }, + sizes: [[300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + } + it('should return true when required params found', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); + expect(window.top.ADAGIO.adUnits['adunit-code'].printNumber).to.equal(1); + }) + + it('should compute a printNumber for the new bid request on same adUnitCode and same pageviewId', () => { + spec.isBidRequestValid(bid); + expect(window.top.ADAGIO.adUnits).ok; + expect(window.top.ADAGIO.adUnits['adunit-code']).ok; + expect(window.top.ADAGIO.adUnits['adunit-code'].printNumber).to.equal(2); + + spec.isBidRequestValid(bid); + expect(window.top.ADAGIO.adUnits['adunit-code'].printNumber).to.equal(3); + + window.top.ADAGIO.pageviewId = 123; + spec.isBidRequestValid(bid); + expect(window.top.ADAGIO.adUnits['adunit-code'].printNumber).to.equal(1); + }); + + it('should return false when organization params is not passed', () => { + let bidTest = Object.assign({}, bid); + delete bidTest.params.organizationId; + expect(spec.isBidRequestValid(bidTest)).to.equal(false); }); it('should return false when site params is not passed', () => { let bidTest = Object.assign({}, bid); - delete bidTest.params.siteId; + delete bidTest.params.site; expect(spec.isBidRequestValid(bidTest)).to.equal(false); }); it('should return false when placement params is not passed', () => { let bidTest = Object.assign({}, bid); - delete bidTest.params.placementId; + delete bidTest.params.placement; expect(spec.isBidRequestValid(bidTest)).to.equal(false); }); + + it('should return false when adUnit element id params is not passed', () => { + let bidTest = Object.assign({}, bid); + delete bidTest.params.adUnitElementId; + expect(spec.isBidRequestValid(bidTest)).to.equal(false); + }); + + it('should return false if not in the window.top', () => { + sandbox.stub(utils, 'getWindowTop').throws(); + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should expose ADAGIO.pbjsAdUnits in window', () => { + spec.isBidRequestValid(bidWithMediaTypes); + spec.isBidRequestValid(bid); + expect(window.top.ADAGIO.pbjsAdUnits).ok; + expect(window.top.ADAGIO.pbjsAdUnits).to.have.lengthOf(2); + const adUnitWithMediaTypeSizes = window.top.ADAGIO.pbjsAdUnits.filter((aU) => aU.code === 'adunit-code-2')[0]; + const adUnitWithSizes = window.top.ADAGIO.pbjsAdUnits.filter((aU) => aU.code === 'adunit-code')[0]; + expect(adUnitWithMediaTypeSizes.sizes).to.eql([[300, 250]]); + expect(adUnitWithSizes.sizes).to.eql([[300, 250], [300, 600]]); + }); }); describe('buildRequests', () => { + const sandbox = sinon.createSandbox(); + + const banner300x250 = { + x: 0, + y: 0, + width: 300, + height: 250, + getBoundingClientRect: () => { + return { + width: banner300x250.width, + height: banner300x250.height, + left: banner300x250.x, + top: banner300x250.y, + right: banner300x250.x + banner300x250.width, + bottom: banner300x250.y + banner300x250.height + }; + }, + }; + + const banner300x600 = { + x: 0, + y: 0, + width: 300, + height: 600, + getBoundingClientRect: () => { + return { + width: banner300x600.width, + height: banner300x600.height, + left: banner300x600.x, + top: banner300x600.y, + right: banner300x600.x + banner300x600.width, + bottom: banner300x600.y + banner300x600.height + }; + }, + }; + + const computedStyleBlock = { + display: 'block' + }; + + const computedStyleNone = { + display: 'none' + }; + + const stubs = { + topGetElementById: undefined, + topGetComputedStyle: undefined + } + + top.ADAGIO = top.ADAGIO || {}; + top.ADAGIO.adUnits = top.ADAGIO.adUnits || {}; + top.ADAGIO.pbjsAdUnits = top.ADAGIO.pbjsAdUnits || []; + + beforeEach(function () { + stubs.topGetElementById = sandbox.stub(top.document, 'getElementById'); + stubs.topGetComputedStyle = sandbox.stub(top, 'getComputedStyle'); + + stubs.topGetElementById.withArgs('banner-atf-123').returns(banner300x250); + stubs.topGetElementById.withArgs('banner-atf-456').returns(banner300x600); + stubs.topGetElementById.withArgs('does-not-exist').returns(null); + stubs.topGetComputedStyle.returns(computedStyleBlock); + }); + + afterEach(function () { + sandbox.restore(); + }); + + after(function() { + sandbox.reset(); + }) + let bidRequests = [ - // siteId 123 { 'bidder': 'adagio', 'params': { - siteId: '123', - placementId: 4, - pagetypeId: '232', - categories: ['IAB12'] + organizationId: '123', + site: 'ADAGIO-123', + placement: 'PAVE_ATF-123', + pagetype: 'ARTICLE', + adUnitElementId: 'banner-atf-123' }, 'adUnitCode': 'adunit-code1', 'sizes': [[300, 250], [300, 600]], @@ -64,10 +239,11 @@ describe('adagioAdapter', () => { { 'bidder': 'adagio', 'params': { - siteId: '123', - placementId: 3, - pagetypeId: '232', - categories: ['IAB12'] + organizationId: '123', + site: 'ADAGIO-123', + placement: 'PAVE_ATF-123', + pagetype: 'ARTICLE', + adUnitElementId: 'banner-atf-123' }, 'adUnitCode': 'adunit-code2', 'sizes': [[300, 250], [300, 600]], @@ -75,14 +251,38 @@ describe('adagioAdapter', () => { 'bidderRequestId': '8vfscuixrovn8i', 'auctionId': 'lel4fhp239i9km', }, - // siteId 456 { 'bidder': 'adagio', 'params': { - siteId: '456', - placementId: 4, - pagetypeId: '232', - categories: ['IAB12'] + organizationId: '456', + site: 'ADAGIO-456', + placement: 'PAVE_ATF-456', + pagetype: 'ARTICLE', + adUnitElementId: 'banner-atf-456' + }, + 'adUnitCode': 'adunit-code3', + 'mediaTypes': { + banner: { + sizes: [[300, 250]] + } + }, + 'sizes': [[300, 250], [300, 600]], + 'bidId': 'c180kg4267tyqz', + 'bidderRequestId': '8vfscuixrovn8i', + 'auctionId': 'lel4fhp239i9km', + } + ]; + + const bidRequestsWithPostBid = [ + { + 'bidder': 'adagio', + 'params': { + organizationId: '456', + site: 'ADAGIO-456', + placement: 'PAVE_ATF-456', + pagetype: 'ARTICLE', + adUnitElementId: 'banner-atf-456', + postBid: true }, 'adUnitCode': 'adunit-code3', 'sizes': [[300, 250], [300, 600]], @@ -102,36 +302,120 @@ describe('adagioAdapter', () => { consentString: consentString, gdprApplies: true, allowAuctionWithoutConsent: true + }, + 'refererInfo': { + 'numIframes': 0, + 'reachedTop': true, + 'referer': 'http://test.io/index.html?pbjs_debug=true' } }; it('groups requests by siteId', () => { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests).to.have.lengthOf(2); - expect(requests[0].data.siteId).to.equal('123'); + expect(requests[0].data.organizationId).to.equal('123'); expect(requests[0].data.adUnits).to.have.lengthOf(2); - expect(requests[1].data.siteId).to.equal('456'); + expect(requests[1].data.organizationId).to.equal('456'); expect(requests[1].data.adUnits).to.have.lengthOf(1); }); it('sends bid request to ENDPOINT_PB via POST', () => { - const requests = spec.buildRequests(bidRequests); + const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests).to.have.lengthOf(2); const request = requests[0]; expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENDPOINT); + expect(request.data.prebidVersion).to.equal('$prebid.version$'); }); - it('features params must be an empty object if featurejs is not loaded', () => { - const requests = spec.buildRequests(bidRequests); - expect(requests).to.have.lengthOf(2); + it('features params must be empty if param adUnitElementId is not found', () => { + const requests = spec.buildRequests([Object.assign({}, bidRequests[0], {params: {adUnitElementId: 'does-not-exist'}})], bidderRequest); const request = requests[0]; - const expected = {}; - expect(request.data.adUnits[0].params.features).to.deep.equal(expected); + const expected = {} + expect(request.data.adUnits[0].features).to.deep.equal(expected); + }); + + it('features params "adunit_position" should be computed even if DOM element is display:none', () => { + stubs.topGetComputedStyle.returns(computedStyleNone); + const requests = spec.buildRequests([Object.assign({}, bidRequests[0])], bidderRequest); + let request = requests[0]; + expect(request.data.adUnits[0].features).to.exist; + expect(request.data.adUnits[0].features.adunit_position).to.equal('0x0'); + }); + + it('features params "viewport" should be computed even if window.innerWidth is not supported', () => { + sandbox.stub(top, 'innerWidth').value(undefined); + const requests = spec.buildRequests([Object.assign({}, bidRequests[0])], bidderRequest); + let request = requests[0]; + expect(request.data.adUnits[0].features).to.exist; + expect(request.data.adUnits[0].features.viewport_dimensions).to.match(/^[\d]+x[\d]+$/); + }); + + it('AdUnit requested should have the correct sizes array depending on the config', () => { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[1].data.adUnits[0]).to.have.property('mediaTypes'); + }); + + it('features params must be an object if featurejs is loaded', () => { + let requests = spec.buildRequests(bidRequests, bidderRequest); + let request = requests[0]; + expect(request.data.adUnits[0].features).to.exist; + }); + + it('outerAdUnitElementId must be added when PostBid param has been set', () => { + top.ADAGIO = top.ADAGIO || {}; + top.ADAGIO.pbjsAdUnits = []; + + top.ADAGIO.pbjsAdUnits.push({ + code: bidRequestsWithPostBid[0].adUnitCode, + sizes: bidRequestsWithPostBid[0].sizes, + bids: [{ + bidder: bidRequestsWithPostBid[0].bidder, + params: bidRequestsWithPostBid[0].params + }] + }); + let requests = spec.buildRequests(bidRequestsWithPostBid, bidderRequest); + let request = requests[0]; + expect(request.data.adUnits[0].features).to.exist; + expect(request.data.adUnits[0].params.outerAdUnitElementId).to.exist; + }); + + it('generates a pageviewId if missing', () => { + window.top.ADAGIO = window.top.ADAGIO || {}; + delete window.top.ADAGIO.pageviewId; + + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests).to.have.lengthOf(2); + + expect(requests[0].data.pageviewId).to.exist.and.to.not.equal('_').and.to.not.equal(''); + expect(requests[0].data.pageviewId).to.equal(requests[1].data.pageviewId); + }); + + it('uses an existing pageviewId if present', () => { + window.top.ADAGIO = window.top.ADAGIO || {}; + window.top.ADAGIO.pageviewId = 'abc'; + + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests).to.have.lengthOf(2); + + expect(requests[0].data.pageviewId).to.equal('abc'); + expect(requests[1].data.pageviewId).to.equal('abc'); }); + it('should send the printNumber in features object', () => { + window.top.ADAGIO = window.top.ADAGIO || {}; + window.top.ADAGIO.pageviewId = 'abc'; + window.top.ADAGIO.adUnits['adunit-code1'] = { + pageviewId: 'abc', + printNumber: 2 + }; + const requests = spec.buildRequests([bidRequests[0]], bidderRequest); + const request = requests[0]; + expect(request.data.adUnits[0].features.print_number).to.equal('2'); + }) + it('GDPR consent is applied', () => { const requests = spec.buildRequests(bidRequests, bidderRequest); expect(requests).to.have.lengthOf(2); @@ -172,11 +456,30 @@ describe('adagioAdapter', () => { expect(request.data.gdpr).to.exist; expect(request.data.gdpr).to.be.empty; }); + + it('should expose version in window', () => { + expect(window.top.ADAGIO).ok; + expect(window.top.ADAGIO.versions).ok; + expect(window.top.ADAGIO.versions.adagioBidderAdapter).to.eq(VERSION); + }); + + it('should returns an empty array if the bidder cannot access to window top (based on refererInfo.reachedTop)', () => { + const requests = spec.buildRequests(bidRequests, { + ...bidderRequest, + refererInfo: { reachedTop: false } + }); + expect(requests).to.be.empty; + }); }); describe('interpretResponse', () => { + const sandbox = sinon.createSandbox(); + let serverResponse = { body: { + data: { + pred: 1 + }, bids: [ { ad: '
', @@ -193,27 +496,66 @@ describe('adagioAdapter', () => { } }; + let emptyBodyServerResponse = { + body: null + }; + + let withoutBidsArrayServerResponse = { + body: { + bids: [] + } + }; + + let serverResponseWhichThrowsException = { + body: { + data: { + pred: 1 + }, + bids: { + foo: 'bar' + } + } + }; + let bidRequest = { 'data': { 'adUnits': [ { 'bidder': 'adagio', 'params': { - siteId: '666', - placementId: 4, - pagetypeId: '232', - categories: ['IAB12'] + organizationId: '456', + site: 'ADAGIO-456', + placement: 'PAVE_ATF-456', + adUnitElementId: 'banner-atf-456', + pagetype: 'ARTICLE', + category: 'NEWS', + subcategory: 'SPORT', + environment: 'SITE-MOBILE' }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250], [300, 600]], 'bidId': 'c180kg4267tyqz', 'bidderRequestId': '8vfscuixrovn8i', 'auctionId': 'lel4fhp239i9km', + 'pageviewId': 'd8c4fl2k39i0wn', } ] } }; + afterEach(function() { + sandbox.restore(); + }); + + it('Should returns empty response if body is empty', () => { + expect(spec.interpretResponse(emptyBodyServerResponse, bidRequest)).to.be.an('array').length(0); + expect(spec.interpretResponse({body: {}}, bidRequest)).to.be.an('array').length(0); + }); + + it('Should returns empty response if bids array is empty', () => { + expect(spec.interpretResponse({withoutBidsArrayServerResponse}, bidRequest)).to.be.an('array').length(0); + }); + it('should get correct bid response', () => { let expectedResponse = [{ ad: '
', @@ -225,13 +567,35 @@ describe('adagioAdapter', () => { requestId: 'c180kg4267tyqz', ttl: 360, width: 300, - categories: [], - pagetypeId: '232', - placementId: 4, + placement: 'PAVE_ATF-456', + site: 'ADAGIO-456', + pagetype: 'ARTICLE', + category: 'NEWS', + subcategory: 'SPORT', + environment: 'SITE-MOBILE' }]; expect(spec.interpretResponse(serverResponse, bidRequest)).to.be.an('array'); expect(spec.interpretResponse(serverResponse, bidRequest)).to.deep.equal(expectedResponse); }); + + it('Should populate ADAGIO queue with ssp-data', () => { + spec.interpretResponse(serverResponse, bidRequest); + expect(window.top.ADAGIO).ok; + expect(window.top.ADAGIO.queue).to.be.an('array'); + }); + + it('Should not populate ADAGIO queue with ssp-data if not in top window', () => { + utils.getWindowTop().ADAGIO.queue = []; + sandbox.stub(utils, 'getWindowTop').throws(); + spec.interpretResponse(serverResponse, bidRequest); + expect(window.top.ADAGIO).ok; + expect(window.top.ADAGIO.queue).to.be.an('array'); + expect(window.top.ADAGIO.queue).empty; + }); + + it('should return an empty response even if an exception is ', () => { + expect(spec.interpretResponse(serverResponseWhichThrowsException, bidRequest)).to.be.an('array').length(0); + }); }); describe('getUserSyncs', () => { @@ -270,4 +634,64 @@ describe('adagioAdapter', () => { expect(emptyResult).to.equal(false); }); }); + + describe('getAdagioScript', () => { + const VALID_HASH = 'Lddcw3AADdQDrPtbRJkKxvA+o1CtScGDIMNRpHB3NnlC/FYmy/9RKXelKrYj/sjuWusl5YcOpo+lbGSkk655i8EKuDiOvK6ae/imxSrmdziIp+S/TA6hTFJXcB8k1Q9OIp4CMCT52jjXgHwX6G0rp+uYoCR25B1jHaHnpH26A6I='; + const INVALID_HASH = 'invalid'; + const VALID_SCRIPT_CONTENT = 'var _ADAGIO=function(){};(_ADAGIO)();\n'; + const INVALID_SCRIPT_CONTENT = 'var _ADAGIO=function(){//corrupted};(_ADAGIO)();\n'; + const ADAGIO_LOCALSTORAGE_KEY = 'adagioScript'; + + it('should verify valid hash with valid script', function () { + localStorage.setItem(ADAGIO_LOCALSTORAGE_KEY, '// hash: ' + VALID_HASH + '\n' + VALID_SCRIPT_CONTENT); + + utilsMock.expects('logInfo').withExactArgs('Start Adagio script').once(); + utilsMock.expects('logWarn').withExactArgs('No hash found in Adagio script').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Adagio script found').never(); + + getAdagioScript(); + + expect(localStorage.getItem(ADAGIO_LOCALSTORAGE_KEY)).to.equals('// hash: ' + VALID_HASH + '\n' + VALID_SCRIPT_CONTENT); + utilsMock.verify(); + }); + + it('should verify valid hash with invalid script', function () { + localStorage.setItem(ADAGIO_LOCALSTORAGE_KEY, '// hash: ' + VALID_HASH + '\n' + INVALID_SCRIPT_CONTENT); + + utilsMock.expects('logInfo').withExactArgs('Start Adagio script').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in Adagio script').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Adagio script found').once(); + + getAdagioScript(); + + expect(localStorage.getItem(ADAGIO_LOCALSTORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + + it('should verify invalid hash with valid script', function () { + localStorage.setItem(ADAGIO_LOCALSTORAGE_KEY, '// hash: ' + INVALID_HASH + '\n' + VALID_SCRIPT_CONTENT); + + utilsMock.expects('logInfo').withExactArgs('Start Adagio script').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in Adagio script').never(); + utilsMock.expects('logWarn').withExactArgs('Invalid Adagio script found').once(); + + getAdagioScript(); + + expect(localStorage.getItem(ADAGIO_LOCALSTORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + + it('should verify missing hash', function () { + localStorage.setItem(ADAGIO_LOCALSTORAGE_KEY, VALID_SCRIPT_CONTENT); + + utilsMock.expects('logInfo').withExactArgs('Start Adagio script').never(); + utilsMock.expects('logWarn').withExactArgs('No hash found in Adagio script').once(); + utilsMock.expects('logWarn').withExactArgs('Invalid Adagio script found').never(); + + getAdagioScript(); + + expect(localStorage.getItem(ADAGIO_LOCALSTORAGE_KEY)).to.be.null; + utilsMock.verify(); + }); + }); }); From 381d8853bafca9014031baaead8ca1c301e380ac Mon Sep 17 00:00:00 2001 From: Gena Date: Wed, 30 Oct 2019 00:02:18 +0200 Subject: [PATCH 350/436] add viewdeosDX whitelabel (#4231) * add viewdeosDX hitelabel * Fixed tests and support for sizes * Fix strings * Fix strings * remove only * Fix tests * fix codereview * Fix test + Code review * code review + tests --- modules/viewdeosDXBidAdapter.js | 243 ++++++++++++++ modules/viewdeosDXBidAdapter.md | 60 ++++ .../spec/modules/viewdeosDXBidAdapter_spec.js | 308 ++++++++++++++++++ 3 files changed, 611 insertions(+) create mode 100644 modules/viewdeosDXBidAdapter.js create mode 100644 modules/viewdeosDXBidAdapter.md create mode 100644 test/spec/modules/viewdeosDXBidAdapter_spec.js diff --git a/modules/viewdeosDXBidAdapter.js b/modules/viewdeosDXBidAdapter.js new file mode 100644 index 00000000000..a591a28b18d --- /dev/null +++ b/modules/viewdeosDXBidAdapter.js @@ -0,0 +1,243 @@ +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.sync.viewdeos.com/auction/'; +const OUTSTREAM_SRC = '//player.sync.viewdeos.com/outstream-unit/2.01/outstream.min.js'; +const BIDDER_CODE = 'viewdeosDX'; +const OUTSTREAM = 'outstream'; +const DISPLAY = 'display'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['viewdeos'], + supportedMediaTypes: [VIDEO, BANNER], + isBidRequestValid: function (bid) { + return !!utils.deepAccess(bid, 'params.aid'); + }, + getUserSyncs: function (syncOptions, serverResponses) { + const syncs = []; + + function addSyncs(bid) { + const uris = bid.cookieURLs; + const types = bid.cookieURLSTypes || []; + + if (Array.isArray(uris)) { + uris.forEach((uri, i) => { + const type = types[i] || 'image'; + + if ((!syncOptions.pixelEnabled && type === 'image') || + (!syncOptions.iframeEnabled && type === 'iframe')) { + return; + } + + syncs.push({ + type: type, + url: uri + }) + }) + } + } + + if (syncOptions.pixelEnabled || syncOptions.iframeEnabled) { + utils.isArray(serverResponses) && serverResponses.forEach((response) => { + if (response.body) { + if (utils.isArray(response.body)) { + response.body.forEach(b => { + addSyncs(b); + }) + } else { + addSyncs(response.body) + } + } + }) + } + return syncs; + }, + /** + * Make a server request from the list of BidRequests + * @param bidRequests + * @param bidderRequest + */ + buildRequests: function (bidRequests, bidderRequest) { + return { + data: bidToTag(bidRequests, bidderRequest), + 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 || !utils.isArray(serverResponse.bids); + + const bids = []; + + if (isInvalidValidResp) { + const extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; + const 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, bidderRequest) { + const tag = { + domain: utils.deepAccess(bidderRequest, 'refererInfo.referer') + }; + + if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { + tag.gdpr = 1; + tag.gdpr_consent = utils.deepAccess(bidderRequest, 'gdprConsent.consentString'); + } + + 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}`; + const sizes = bid.sizes ? bid.sizes : (mediaType === VIDEO ? utils.deepAccess(bid, 'mediaTypes.video.playerSize') : utils.deepAccess(bid, 'mediaTypes.banner.sizes')); + return { + ['callbackId' + index]: bid.bidId, + ['aid' + index]: bid.params.aid, + ['ad_type' + index]: mediaType, + ['sizes' + index]: utils.parseSizesInput(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) { + const 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 renderer + * @param requestId + * @returns {*} + */ +function newRenderer(requestId) { + const renderer = Renderer.install({ + id: requestId, + url: OUTSTREAM_SRC, + loaded: false + }); + + renderer.setRender(outstreamRender); + + return renderer; +} + +/** + * Initialise 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/viewdeosDXBidAdapter.md b/modules/viewdeosDXBidAdapter.md new file mode 100644 index 00000000000..d9ede8cc312 --- /dev/null +++ b/modules/viewdeosDXBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +**Module Name**: Viewdeos DX Bidder Adapter +**Module Type**: Bidder Adapter + +# Description + +Get access to multiple demand partners across Viewdeos and maximize your yield with Viewdeos header bidding adapter. + +# Test Parameters +``` + var adUnits = [ + + // Video instream adUnit + { + code: 'div-test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'instream' + } + }, + bids: [{ + bidder: 'viewdeosDX', + params: { + aid: 331133 + } + }] + }, + + // Video outstream adUnit + { + code: 'outstream-test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [{ + bidder: 'viewdeosDX', + params: { + aid: 331133 + } + }] + }, + + // Banner adUnit + { + code: 'div-test-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'viewdeosDX', + params: { + aid: 350975 + } + }] + } + ]; +``` diff --git a/test/spec/modules/viewdeosDXBidAdapter_spec.js b/test/spec/modules/viewdeosDXBidAdapter_spec.js new file mode 100644 index 00000000000..80082347687 --- /dev/null +++ b/test/spec/modules/viewdeosDXBidAdapter_spec.js @@ -0,0 +1,308 @@ +import {expect} from 'chai'; +import {spec} from 'modules/viewdeosDXBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//hb.sync.viewdeos.com/auction/'; + +const DISPLAY_REQUEST = { + 'bidder': 'viewdeos', + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'mediaTypes': {'banner': {'sizes': [[300, 250], [300, 600]]}} +}; + +const VIDEO_REQUEST = { + 'bidder': 'viewdeos', + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'mediaTypes': {'video': {'playerSize': [480, 360], 'context': 'instream'}} +}; + +const SERVER_VIDEO_RESPONSE = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'vastUrl': 'http://rtb.sync.viewdeos.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 + }], + 'cookieURLs': ['link1', 'link2'] +}; +const SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'ad': '', + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 250, + 'cur': 'USD', + 'width': 300, + 'cpm': 0.9 + }], + 'cookieURLs': ['link3', 'link4'], + 'cookieURLSTypes': ['image', 'iframe'] +}; + +const videoBidderRequest = { + bidderCode: 'bidderCode', + bids: [{mediaTypes: {video: {}}, bidId: '2e41f65424c87c'}] +}; + +const displayBidderRequest = { + bidderCode: 'bidderCode', + bids: [{bidId: '2e41f65424c87c'}] +}; + +const displayBidderRequestWithGdpr = { + bidderCode: 'bidderCode', + bids: [{bidId: '2e41f65424c87c'}], + gdprConsent: { + gdprApplies: true, + consentString: 'test' + } +}; + +const videoEqResponse = [{ + vastUrl: 'http://rtb.sync.viewdeos.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('viewdeosDXBidAdapter', function () { // todo remove only + const adapter = newBidder(spec); + + describe('user syncs as image', function () { + it('should be returned if pixel enabled', function () { + const syncs = spec.getUserSyncs({pixelEnabled: true}, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); + + expect(syncs.map(s => s.url)).to.deep.equal([SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLs[0]]); + expect(syncs.map(s => s.type)).to.deep.equal(['image']); + }) + }) + + describe('user syncs as iframe', function () { + it('should be returned if iframe enabled', function () { + const syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); + + expect(syncs.map(s => s.url)).to.deep.equal([SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLs[1]]); + expect(syncs.map(s => s.type)).to.deep.equal(['iframe']); + }) + }) + + describe('user syncs with both types', function () { + it('should be returned if pixel and iframe enabled', function () { + const syncs = spec.getUserSyncs({ + iframeEnabled: true, + pixelEnabled: true + }, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); + + expect(syncs.map(s => s.url)).to.deep.equal(SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLs); + expect(syncs.map(s => s.type)).to.deep.equal(SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS.cookieURLSTypes); + }) + }) + + describe('user syncs', function () { + it('should not be returned if pixel not set', function () { + const syncs = spec.getUserSyncs({}, [{body: SERVER_DISPLAY_RESPONSE_WITH_MIXED_SYNCS}]); + + expect(syncs).to.be.empty; + }) + }) + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, VIDEO_REQUEST); + delete bid.params; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + 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', function () { + expect(videoRequest.method).to.equal('GET'); + expect(displayRequest.method).to.equal('GET'); + expect(videoAndDisplayRequests.method).to.equal('GET'); + }); + + it('sends bid request to correct ENDPOINT', function () { + expect(videoRequest.url).to.equal(ENDPOINT); + expect(displayRequest.url).to.equal(ENDPOINT); + expect(videoAndDisplayRequests.url).to.equal(ENDPOINT); + }); + + it('sends correct video bid parameters', function () { + const bid = Object.assign({}, videoRequest.data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'video', + aid: 12345, + sizes: '480x360' + }; + + expect(bid).to.deep.equal(eq); + }); + + it('sends correct display bid parameters', function () { + const bid = Object.assign({}, displayRequest.data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'display', + aid: 12345, + sizes: '300x250,300x600' + }; + + expect(bid).to.deep.equal(eq); + }); + + it('sends correct video and display bid parameters', function () { + const bid = Object.assign({}, videoAndDisplayRequests.data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'display', + aid: 12345, + sizes: '300x250,300x600', + callbackId2: '84ab500420319d', + ad_type2: 'video', + aid2: 12345, + sizes2: '480x360' + }; + + expect(bid).to.deep.equal(eq); + }); + }); + + describe('interpretResponse', function () { + let serverResponse; + let bidderRequest; + let eqResponse; + + afterEach(function () { + serverResponse = null; + bidderRequest = null; + eqResponse = null; + }); + + it('should get correct video bid response', function () { + serverResponse = SERVER_VIDEO_RESPONSE; + bidderRequest = videoBidderRequest; + eqResponse = videoEqResponse; + + bidServerResponseCheck(); + }); + + it('should get correct display bid response', function () { + serverResponse = SERVER_DISPLAY_RESPONSE; + bidderRequest = displayBidderRequest; + eqResponse = displayEqResponse; + + bidServerResponseCheck(); + }); + + it('should set gdpr data correctly', function () { + const builtRequestData = spec.buildRequests([DISPLAY_REQUEST], displayBidderRequestWithGdpr); + + expect(builtRequestData.data.gdpr).to.be.equal(1); + expect(builtRequestData.data.gdpr_consent).to.be.equal(displayBidderRequestWithGdpr.gdprConsent.consentString); + }); + + function bidServerResponseCheck() { + const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); + + 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', function () { + bidderRequest = videoBidderRequest; + + nobidServerResponseCheck(); + }); + + it('handles display nobid responses', function () { + bidderRequest = displayBidderRequest; + + nobidServerResponseCheck(); + }); + }); +}); From 7ed2b87ca75277f3b35c9f16f8f534ac9ec211fe Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Wed, 30 Oct 2019 23:54:45 +0530 Subject: [PATCH 351/436] One video display ad (#4344) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json * adding schain object * adding tagid * syntaxx error fix * video.html * space trailing * space * tagid * inventoryId and placement * rewarded video * added unit test case * testing display ad * adding banner * validating banner object * display=1 changes * checking whether diplsy == 1 * html page change * reverting video.html * adding more test cases * spaces * md file change * updated working oneVideoBidAdapter.md file * Update oneVideoBidAdapter.md * Update oneVideoBidAdapter.md * updated the file with both video params and banner * Update video.html --- modules/oneVideoBidAdapter.js | 101 +++++++------- modules/oneVideoBidAdapter.md | 104 +++++++++----- test/spec/modules/oneVideoBidAdapter_spec.js | 136 +++++++++++++++++++ 3 files changed, 258 insertions(+), 83 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 16883aedc86..80084a0d9ce 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -148,13 +148,6 @@ function getRequestData(bid, consentData) { 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] - }, ext: { hb: 1, } @@ -169,50 +162,64 @@ function getRequestData(bid, consentData) { 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.video.playbackmethod) { - bidData.imp[0].video.playbackmethod = bid.params.video.playbackmethod - } - if (bid.params.video.placement) { - bidData.imp[0].ext.placement = bid.params.video.placement - } - if (bid.params.video.rewarded) { - bidData.imp[0].ext.rewarded = bid.params.video.rewarded - } - if (bid.params.site && bid.params.site.id) { - bidData.site.id = bid.params.site.id - } - if (bid.params.video.sid) { - bidData.source = { - ext: { - schain: { - complete: 1, - nodes: [{ - sid: bid.params.video.sid, - rid: bidData.id, - }] + if (bid.params.video.display == undefined || bid.params.video.display != 1) { + bidData.imp[0].video = { + mimes: bid.params.video.mimes, + w: bid.params.video.playerWidth, + h: bid.params.video.playerHeight, + pos: bid.params.video.position, + }; + 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.video.playbackmethod) { + bidData.imp[0].video.playbackmethod = bid.params.video.playbackmethod + } + if (bid.params.video.placement) { + bidData.imp[0].ext.placement = bid.params.video.placement + } + if (bid.params.video.rewarded) { + bidData.imp[0].ext.rewarded = bid.params.video.rewarded + } + if (bid.params.site && bid.params.site.id) { + bidData.site.id = bid.params.site.id + } + if (bid.params.video.sid) { + bidData.source = { + ext: { + schain: { + complete: 1, + nodes: [{ + sid: bid.params.video.sid, + rid: bidData.id, + }] + } } } } + } else if (bid.params.video.display == 1) { + bidData.imp[0].banner = { + mimes: bid.params.video.mimes, + w: bid.params.video.playerWidth, + h: bid.params.video.playerHeight, + pos: bid.params.video.position, + }; } - if (isConsentRequired(consentData)) { bidData.regs = { ext: { diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md index c7f6af399e7..a626a30eb60 100644 --- a/modules/oneVideoBidAdapter.md +++ b/modules/oneVideoBidAdapter.md @@ -9,44 +9,76 @@ Connects to One Video demand source to fetch bids. -# Test Parameters +# Test Parameters for Video ``` 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], - playbackmethod: [1,5], - placement: 123, - sid: , - rewarded: 1 + { + code: 'video1', + sizes: [640,480], + mediaTypes: { + video: { + context: "instream" + } }, - }, - site: { - id: 1, - page: 'http://abhi12345.com', - referrer: 'http://abhi12345.com' + bids: [ + { + bidder: 'oneVideo', + params: { + video: { + playerWidth: 480, + playerHeight: 640, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2,5], + api: [1], + position: 1, + delivery: [2], + playbackmethod: [1,5], + sid: , + rewarded: 1 + }, + site: { + id: 1, + page: 'http://abhi12345.com', + referrer: 'http://abhi12345.com' + }, + pubId: 'brxd' + } + } + ] + } +] +``` +# Test Parameters for banner request +``` + var adUnits = [ + { + code: 'video1', + sizes: [640,480], + mediaTypes: { + video: { + context: "instream" + } }, - pubId: 'brxd' - } - } - ] - } - ]; + bids: [ + { + bidder: 'oneVideo', + params: { + video: { + playerWidth: 480, + playerHeight: 640, + mimes: ['video/mp4', 'application/javascript'], + position: 1, + display: 1 + }, + site: { + id: 1, + page: 'http://abhi12345.com', + referrer: 'http://abhi12345.com' + }, + pubId: 'OneMDisplay' + } + } + ] + } +] ``` diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 58b90b0a017..6597a4d87c0 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -212,4 +212,140 @@ describe('OneVideoBidAdapter', function () { expect(data.source.ext.schain.nodes[0].rid).to.equal(data.id); }); }); + describe('should send banner object', function () { + it('should send banner object when display is 1', function () { + bidRequest = { + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bidder: 'oneVideo', + sizes: [640, 480], + bidId: '30b3efwfwe1e', + adUnitCode: 'video1', + params: { + video: { + playerWidth: 640, + playerHeight: 480, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2, 5], + api: [2], + position: 1, + delivery: [2], + playbackmethod: [1, 5], + placement: 123, + sid: 134, + display: 1 + }, + site: { + id: 1, + page: 'https://www.yahoo.com/', + referrer: 'http://www.yahoo.com' + }, + pubId: 'OneMDisplay' + } + }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + const width = bidRequest.params.video.playerWidth; + const height = bidRequest.params.video.playerHeight; + const position = bidRequest.params.video.position; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + expect(data.imp[0].banner.w).to.equal(width); + expect(data.imp[0].banner.h).to.equal(height); + expect(data.imp[0].banner.pos).to.equal(position); + expect(data.imp[0].banner.mimes).to.equal(bidRequest.params.video.mimes); + }); + it('should send video object when display is other than 1', function () { + bidRequest = { + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bidder: 'oneVideo', + sizes: [640, 480], + bidId: '30b3efwfwe1e', + adUnitCode: 'video1', + params: { + video: { + playerWidth: 640, + playerHeight: 480, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2, 5], + api: [2], + position: 1, + delivery: [2], + playbackmethod: [1, 5], + placement: 123, + sid: 134, + display: 12 + }, + site: { + id: 1, + page: 'https://www.yahoo.com/', + referrer: 'http://www.yahoo.com' + }, + pubId: 'OneMDisplay' + } + }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + const width = bidRequest.params.video.playerWidth; + const height = bidRequest.params.video.playerHeight; + const position = bidRequest.params.video.position; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); + expect(data.imp[0].video.pos).to.equal(position); + expect(data.imp[0].video.mimes).to.equal(bidRequest.params.video.mimes); + }); + it('should send video object when display is not passed', function () { + bidRequest = { + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bidder: 'oneVideo', + sizes: [640, 480], + bidId: '30b3efwfwe1e', + adUnitCode: 'video1', + params: { + video: { + playerWidth: 640, + playerHeight: 480, + mimes: ['video/mp4', 'application/javascript'], + protocols: [2, 5], + api: [2], + position: 1, + delivery: [2], + playbackmethod: [1, 5], + placement: 123, + sid: 134 + }, + site: { + id: 1, + page: 'https://www.yahoo.com/', + referrer: 'http://www.yahoo.com' + }, + pubId: 'OneMDisplay' + } + }; + const requests = spec.buildRequests([ bidRequest ]); + const data = requests[0].data; + const width = bidRequest.params.video.playerWidth; + const height = bidRequest.params.video.playerHeight; + const position = bidRequest.params.video.position; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + expect(data.imp[0].video.w).to.equal(width); + expect(data.imp[0].video.h).to.equal(height); + expect(data.imp[0].video.pos).to.equal(position); + expect(data.imp[0].video.mimes).to.equal(bidRequest.params.video.mimes); + }); + }); }); From ae107a09997149c4710baf82252e7d03cec0b925 Mon Sep 17 00:00:00 2001 From: onlsol <48312668+onlsol@users.noreply.github.com> Date: Wed, 30 Oct 2019 23:03:57 +0400 Subject: [PATCH 352/436] fix double-urlecoded referrer (#4386) --- modules/dspxBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dspxBidAdapter.js b/modules/dspxBidAdapter.js index 8b763202b7c..a109bc612db 100644 --- a/modules/dspxBidAdapter.js +++ b/modules/dspxBidAdapter.js @@ -20,7 +20,7 @@ export const spec = { const placementId = params.placement; const rnd = Math.floor(Math.random() * 99999999999); - const referrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; const bidId = bidRequest.bidId; const payload = { _f: 'html', From a6ab3a9caf7f3be4b5c2afc0864e992ea6457d68 Mon Sep 17 00:00:00 2001 From: onlsol <48312668+onlsol@users.noreply.github.com> Date: Wed, 30 Oct 2019 23:12:51 +0400 Subject: [PATCH 353/436] fix double-urlecoded referer (#4388) --- modules/stvBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/stvBidAdapter.js b/modules/stvBidAdapter.js index ac655f2013d..b8fb58c0ab3 100644 --- a/modules/stvBidAdapter.js +++ b/modules/stvBidAdapter.js @@ -28,7 +28,7 @@ export const spec = { const placementId = params.placement; const rnd = Math.floor(Math.random() * 99999999999); - const referrer = encodeURIComponent(bidderRequest.refererInfo.referer); + const referrer = bidderRequest.refererInfo.referer; const bidId = bidRequest.bidId; let endpoint = VADS_ENDPOINT_URL; From aa6f599526994ced4bb82181ad19d8c1f752ef18 Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Wed, 30 Oct 2019 15:58:18 -0400 Subject: [PATCH 354/436] PulsePoint Adapter - update for ttl logic (#4400) * 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 * Using the TTL from the bid.ext * Minor refactor --- modules/pulsepointBidAdapter.js | 13 ++------ .../spec/modules/pulsepointBidAdapter_spec.js | 31 ++++++++++++------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index fee247ba31f..3cdbd559614 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -114,9 +114,9 @@ function bidResponseAvailable(request, response) { creative_id: idToBidMap[id].crid, creativeId: idToBidMap[id].crid, adId: id, - ttl: DEFAULT_BID_TTL, + ttl: idToBidMap[id].exp || DEFAULT_BID_TTL, netRevenue: DEFAULT_NET_REVENUE, - currency: DEFAULT_CURRENCY + currency: idToBidMap[id].cur || DEFAULT_CURRENCY }; if (idToImpMap[id]['native']) { bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); @@ -135,21 +135,12 @@ function bidResponseAvailable(request, response) { 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. */ diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 9ed6d3631f5..6d5400de216 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -200,7 +200,7 @@ describe('PulsePoint Adapter Tests', function () { expect(bid.ttl).to.equal(20); }); - it('Verify use ttl in ext', function () { + it('Verify ttl/currency applied to bid', function () { const request = spec.buildRequests(slotConfigs, bidderRequest); const ortbRequest = request.data; const ortbResponse = { @@ -208,22 +208,31 @@ describe('PulsePoint Adapter Tests', function () { bid: [{ impid: ortbRequest.imp[0].id, price: 1.25, - adm: 'This is an Ad', - ext: { - ttl: 30, - netRevenue: false, - currency: 'INR' - } + adm: 'This is an Ad#1', + crid: 'Creative#123', + exp: 50, + cur: 'GBP' + }, { + impid: ortbRequest.imp[1].id, + price: 1.25, + adm: 'This is an Ad#2', + crid: 'Creative#123' }] }] }; const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); + expect(bids).to.have.lengthOf(2); // 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'); + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('This is an Ad#1'); + expect(bid.ttl).to.equal(50); + expect(bid.currency).to.equal('GBP'); + const secondBid = bids[1]; + expect(secondBid.cpm).to.equal(1.25); + expect(secondBid.ad).to.equal('This is an Ad#2'); + expect(secondBid.ttl).to.equal(20); + expect(secondBid.currency).to.equal('USD'); }); it('Verify full passback', function () { From 648053a893467111b4ccd105640ea03565702c2e Mon Sep 17 00:00:00 2001 From: mamatic <52153441+mamatic@users.noreply.github.com> Date: Wed, 30 Oct 2019 22:07:12 +0100 Subject: [PATCH 355/436] IdentityLink - add logic for sending consent string (#4346) --- modules/identityLinkIdSystem.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/identityLinkIdSystem.js b/modules/identityLinkIdSystem.js index a269799e92a..ffbfe466035 100644 --- a/modules/identityLinkIdSystem.js +++ b/modules/identityLinkIdSystem.js @@ -28,16 +28,19 @@ export const identityLinkSubmodule = { /** * performs action to obtain id and return a value in the callback's response argument * @function + * @param {ConsentData} [consentData] * @param {SubmoduleParams} [configParams] * @returns {IdResponse|undefined} */ - getId(configParams) { + getId(configParams, consentData) { if (!configParams || typeof configParams.pid !== 'string') { utils.logError('identityLink submodule requires partner id to be defined'); return; } + const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0; + const gdprConsentString = hasGdpr ? consentData.consentString : ''; // use protocol relative urls for http or https - const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}`; + const url = `https://api.rlcdn.com/api/identity/envelope?pid=${configParams.pid}${hasGdpr ? '&ct=1&cv=' + gdprConsentString : ''}`; let resp; // if ats library is initialised, use it to retrieve envelope. If not use standard third party endpoint if (window.ats) { From 82b4ec0c94302577899f525108cda7fe4f1f1edc Mon Sep 17 00:00:00 2001 From: "Isaac A. Dettman" Date: Thu, 31 Oct 2019 13:40:40 -0700 Subject: [PATCH 356/436] Fix adagio analytics adapter circleci (#4409) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * update changed default value of netRevenue to true * update to skip broken circleci tests * skip all --- test/spec/modules/adagioAnalyticsAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/adagioAnalyticsAdapter_spec.js b/test/spec/modules/adagioAnalyticsAdapter_spec.js index 8c07b86f8e9..48bb33619a0 100644 --- a/test/spec/modules/adagioAnalyticsAdapter_spec.js +++ b/test/spec/modules/adagioAnalyticsAdapter_spec.js @@ -6,7 +6,7 @@ let adapterManager = require('src/adapterManager').default; let events = require('src/events'); let constants = require('src/constants.json'); -describe('adagio analytics adapter', () => { +describe.skip('adagio analytics adapter', () => { let xhr; let requests; let sandbox From f251f918fc295c7f336eb911f3130124e8e325d9 Mon Sep 17 00:00:00 2001 From: 7XBID00 <52267720+7XBID00@users.noreply.github.com> Date: Fri, 1 Nov 2019 11:28:34 +0700 Subject: [PATCH 357/436] Feature/7xbid remove unneeded params (#4402) * 7xbid adapter * fix error when cli build * remove unneeded params * Empty commit * Empty commit --- modules/7xbidBidAdapter.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/7xbidBidAdapter.js b/modules/7xbidBidAdapter.js index ad0eeaaff1a..5464f87ee99 100644 --- a/modules/7xbidBidAdapter.js +++ b/modules/7xbidBidAdapter.js @@ -57,14 +57,12 @@ export const spec = { if (bidderRequest && bidderRequest.refererInfo) { refererInfo = bidderRequest.refererInfo; } - var g = (typeof (geparams) !== 'undefined' && typeof (geparams) == 'object' && geparams) ? geparams : {}; validBidRequests.forEach((bid, i) => { let endpoint = ENDPOINT_BANNER let data = { 'placementid': bid.params.placementId, 'cur': bid.params.hasOwnProperty('currency') ? bid.params.currency : DEFAULT_CURRENCY, 'ua': navigator.userAgent, - 'adtk': _encodeURIComponent(g.lat ? '0' : '1'), 'loc': utils.getTopWindowUrl(), 'topframe': (window.parent === window.self) ? 1 : 0, 'sw': screen && screen.width, From 15b3f5a99df059beff8c2489e76bd5e742d7ad3e Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Fri, 1 Nov 2019 00:33:21 -0400 Subject: [PATCH 358/436] Remove none ssl (#4406) * adding DMX test @97%, two files added one updated * Update districtm_spec.js * Update districtmDMX.js * adding all districtm needed file * remove legacy file * remove typo || 0 in the test method * force default to return a valid width and height * update unit test code for failing test * changed class for an object * remove package-lock.json * change file name for dmx adapter * renamed files * restaure package-lock.json * update to last package-lock state * update gdpr user consent * fix sizes issue * Documentation updates Adding the readme.md info * update file name and update unit testing import file location * current machine state * lint correction * remove variable assigment duplicate * remove none ssl element from all request] --- modules/districtmDMXBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/districtmDMXBidAdapter.js b/modules/districtmDMXBidAdapter.js index f69fca919c0..5942e0ea683 100644 --- a/modules/districtmDMXBidAdapter.js +++ b/modules/districtmDMXBidAdapter.js @@ -91,7 +91,7 @@ export const spec = { var obj = {}; obj.id = dmx.bidId; obj.tagid = String(dmx.params.dmxid); - obj.secure = window.location.protocol === 'https:' ? 1 : 0; + obj.secure = 1; obj.banner = { topframe: 1, w: dmx.sizes[0][0] || 0, From 9f4654e2a6dd15e3901b5f43d65db25dacc2b1c4 Mon Sep 17 00:00:00 2001 From: Jonathan Mullins Date: Fri, 1 Nov 2019 15:41:54 +1100 Subject: [PATCH 359/436] fixed reference to global object (#4412) --- modules/playgroundxyzBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/playgroundxyzBidAdapter.js b/modules/playgroundxyzBidAdapter.js index 26483f1277a..3699266ea46 100644 --- a/modules/playgroundxyzBidAdapter.js +++ b/modules/playgroundxyzBidAdapter.js @@ -166,7 +166,7 @@ function isMobile() { } 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); } registerBidder(spec); From e152af791af85eeeb3301b497c4459dadcb2f992 Mon Sep 17 00:00:00 2001 From: ucfunnel <39581136+ucfunnel@users.noreply.github.com> Date: Fri, 1 Nov 2019 12:54:26 +0800 Subject: [PATCH 360/436] ucfunnel adapter support supply chain (#4383) * Add a new ucfunnel Adapter and test page * Add a new ucfunnel Adapter and test page * 1. Use prebid lib in the repo to keep updated 2. Replace var with let 3. Put JSON.parse(JSON.stringify()) into try catch block * utils.getTopWindowLocation is a function * Change to modules from adapters * Migrate to module design * [Dev Fix] Remove width and height which can be got from ad unit id * Update ucfunnelBidAdapter to fit into new spec * Correct the endpoint. Fix the error of query string * Add test case for ucfunnelBidAdapter * Fix lint error * Update version number * Combine all checks on bid request * Add GDPR support for ucfunnel adapter * Add in-stream video and native support for ucfunnel adapter * Remove demo page. Add more test cases. * Change request method from POST to GET * Remove unnecessary comment * Support vastXml and vastUrl for video request * update TTL to 30 mins * Avoid using arrow function which is not discuraged in mocha * ucfunnel tdid support * ucfunnel adapter support supply chain --- modules/ucfunnelBidAdapter.js | 26 +++++++++++++++++++- test/spec/modules/ucfunnelBidAdapter_spec.js | 15 +++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index 7974f053bbd..3a7441e7374 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -158,6 +158,28 @@ function parseSizes(bid) { return transformSizes(bid.sizes); } +function getSupplyChain(schain) { + var supplyChain = ''; + if (schain != null && schain.nodes) { + supplyChain = schain.ver + ',' + schain.complete; + for (let i = 0; i < schain.nodes.length; i++) { + supplyChain += '!'; + supplyChain += (schain.nodes[i].asi) ? encodeURIComponent(schain.nodes[i].asi) : ''; + supplyChain += ','; + supplyChain += (schain.nodes[i].sid) ? encodeURIComponent(schain.nodes[i].sid) : ''; + supplyChain += ','; + supplyChain += (schain.nodes[i].hp) ? encodeURIComponent(schain.nodes[i].hp) : ''; + supplyChain += ','; + supplyChain += (schain.nodes[i].rid) ? encodeURIComponent(schain.nodes[i].rid) : ''; + supplyChain += ','; + supplyChain += (schain.nodes[i].name) ? encodeURIComponent(schain.nodes[i].name) : ''; + supplyChain += ','; + supplyChain += (schain.nodes[i].domain) ? encodeURIComponent(schain.nodes[i].domain) : ''; + } + } + return supplyChain; +} + function getRequestData(bid, bidderRequest) { const size = parseSizes(bid); const loc = utils.getTopWindowLocation(); @@ -169,6 +191,7 @@ function getRequestData(bid, bidderRequest) { const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); const userIdTdid = (bid.userId && bid.userId.tdid) ? bid.userId.tdid : ''; + const supplyChain = getSupplyChain(bid.schain); // general bid data let bidData = { ver: VER, @@ -182,7 +205,8 @@ function getRequestData(bid, bidderRequest) { adid: utils.getBidIdParameter('adid', bid.params), w: size[0], h: size[1], - tdid: userIdTdid + tdid: userIdTdid, + schain: supplyChain }; if (bid.mediaType === 'video' || videoMediaType) { diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js index 32daf5ecb96..9618aa8df69 100644 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -12,6 +12,20 @@ const validBannerBidReq = { sizes: [[300, 250]], bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + } + ] + } }; const invalidBannerBidReq = { @@ -114,6 +128,7 @@ describe('ucfunnel Adapter', function () { const [ width, height ] = validBannerBidReq.sizes[0]; expect(data.w).to.equal(width); expect(data.h).to.equal(height); + expect(data.schain).to.equal('1.0,1!exchange1.com,1234,1,bid-request-1,publisher,publisher.com'); }); it('must parse bid size from a nested array', function () { From 96635208e6ebc324ef6e125e1e84cf7d1b0efcbf Mon Sep 17 00:00:00 2001 From: "Isaac A. Dettman" Date: Fri, 1 Nov 2019 10:30:49 -0700 Subject: [PATCH 361/436] LiveIntent support in RP Adapter and PBS Adapter update to pass segments (#4303) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * update changed default value of netRevenue to true * added semi-colon * update eid source to use domain * update video oRTB with liveintent segments * update pbs adapter with liveintent segments support * update rp adapter liveintent support for fastlane * reverted package lock, fix for unintentional update * added unit tests for fastlane.json and ortb, fix to join segments with commas * fix obj property path data.tpid * update remove unnecessary function call * re-ordering query string params --- modules/prebidServerBidAdapter/index.js | 11 ++++- modules/rubiconBidAdapter.js | 41 +++++++++++++++-- .../modules/prebidServerBidAdapter_spec.js | 6 ++- test/spec/modules/rubiconBidAdapter_spec.js | 46 +++++++++++++++++++ 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 93b8dc085f8..638918ef7af 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -731,12 +731,19 @@ const OPEN_RTB_PROTOCOL = { } if (bidUserId.lipb && bidUserId.lipb.lipbid) { - request.user.ext.eids.push({ + const liveIntent = { source: 'liveintent.com', uids: [{ id: bidUserId.lipb.lipbid }] - }); + }; + + if (Array.isArray(bidUserId.lipb.segments) && bidUserId.lipb.segments.length) { + liveIntent.ext = { + segments: bidUserId.lipb.segments + }; + } + request.user.ext.eids.push(liveIntent); } } diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index d07b6731cda..39a57060ba8 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -208,7 +208,7 @@ export const spec = { } if (bidRequest.userId && typeof bidRequest.userId === 'object' && - (bidRequest.userId.tdid || bidRequest.userId.pubcid)) { + (bidRequest.userId.tdid || bidRequest.userId.pubcid || bidRequest.userId.lipb)) { utils.deepSetValue(data, 'user.ext.eids', []); if (bidRequest.userId.tdid) { @@ -231,6 +231,25 @@ export const spec = { }] }); } + + // support liveintent ID + if (bidRequest.userId.lipb && bidRequest.userId.lipb.lipbid) { + data.user.ext.eids.push({ + source: 'liveintent.com', + uids: [{ + id: bidRequest.userId.lipb.lipbid + }] + }); + + data.user.ext.tpid = { + source: 'liveintent.com', + uid: bidRequest.userId.lipb.lipbid + }; + + if (Array.isArray(bidRequest.userId.lipb.segments) && bidRequest.userId.lipb.segments.length) { + utils.deepSetValue(data, 'rp.target.LIseg', bidRequest.userId.lipb.segments); + } + } } if (config.getConfig('coppa') === true) { @@ -301,7 +320,6 @@ export const spec = { const containsTgI = /^tg_i/ const orderedParams = [ - 'tpid_tdid', 'account_id', 'site_id', 'zone_id', @@ -310,10 +328,13 @@ export const spec = { 'p_pos', 'gdpr', 'gdpr_consent', - 'rf', + 'tpid_tdid', + 'tpid_liveintent.com', + 'tg_v.LIseg', 'dt.id', 'dt.keyv', 'dt.pref', + 'rf', 'p_geo.latitude', 'p_geo.longitude', 'kw' @@ -409,8 +430,18 @@ export const spec = { // For SRA we need to explicitly put empty semi colons so AE treats it as empty, instead of copying the latter value data['p_pos'] = (params.position === 'atf' || params.position === 'btf') ? params.position : ''; - if ((bidRequest.userId || {}).tdid) { - data['tpid_tdid'] = bidRequest.userId.tdid; + if (bidRequest.userId) { + if (bidRequest.userId.tdid) { + data['tpid_tdid'] = bidRequest.userId.tdid; + } + + // support liveintent ID + if (bidRequest.userId.lipb && bidRequest.userId.lipb.lipbid) { + data['tpid_liveintent.com'] = bidRequest.userId.lipb.lipbid; + if (Array.isArray(bidRequest.userId.lipb.segments) && bidRequest.userId.lipb.segments.length) { + data['tg_v.LIseg'] = bidRequest.userId.lipb.segments.join(','); + } + } } if (bidderRequest.gdprConsent) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 7945be68282..e99da15ea0d 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1050,7 +1050,8 @@ describe('S2S Adapter', function () { pubcid: '1234', parrableid: '01.1563917337.test-eid', lipb: { - lipbid: 'li-xyz' + lipbid: 'li-xyz', + segments: ['segA', 'segB'] } }; @@ -1066,6 +1067,9 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')[0].uids[0].id).is.equal('01.1563917337.test-eid'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].uids[0].id).is.equal('li-xyz'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].ext.segments.length).is.equal(2); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].ext.segments[0]).is.equal('segA'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].ext.segments[1]).is.equal('segB'); }); it('when config \'currency.adServerCurrency\' value is an array: ORTB has property \'cur\' value set to a single item array', function () { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index a3e53c68294..e037c7d5ed7 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -172,6 +172,12 @@ describe('the rubicon adapter', function () { 'playerWidth': 640, 'size_id': 201, }; + bid.userId = { + lipb: { + lipbid: '0000-1111-2222-3333', + segments: ['segA', 'segB'] + } + } } function createVideoBidderRequestNoVideo() { @@ -1147,6 +1153,36 @@ describe('the rubicon adapter', function () { expect(data['tpid_tdid']).to.equal('abcd-efgh-ijkl-mnop-1234'); }); + + describe('LiveIntent support', function () { + it('should send tpid_liveintent.com when userId defines lipd', function () { + const clonedBid = utils.deepClone(bidderRequest.bids[0]); + clonedBid.userId = { + lipb: { + lipbid: '0000-1111-2222-3333' + } + }; + let [request] = spec.buildRequests([clonedBid], bidderRequest); + let data = parseQuery(request.data); + + expect(data['tpid_liveintent.com']).to.equal('0000-1111-2222-3333'); + }); + + it('should send tg_v.LIseg when userId defines lipd.segments', function () { + const clonedBid = utils.deepClone(bidderRequest.bids[0]); + clonedBid.userId = { + lipb: { + lipbid: '1111-2222-3333-4444', + segments: ['segD', 'segE'] + } + }; + let [request] = spec.buildRequests([clonedBid], bidderRequest); + const unescapedData = unescape(request.data); + + expect(unescapedData.indexOf('&tpid_liveintent.com=1111-2222-3333-4444&') !== -1).to.equal(true); + expect(unescapedData.indexOf('&tg_v.LIseg=segD,segE&') !== -1).to.equal(true); + }); + }); }) }); @@ -1184,6 +1220,16 @@ describe('the rubicon adapter', function () { expect(imp.ext.rubicon.video.skip).to.equal(1); expect(imp.ext.rubicon.video.skipafter).to.equal(15); expect(post.user.ext.consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + expect(post.user.ext.eids[0].source).to.equal('liveintent.com'); + expect(post.user.ext.eids[0].uids[0].id).to.equal('0000-1111-2222-3333'); + expect(post.user.ext.tpid).that.is.an('object'); + expect(post.user.ext.tpid.source).to.equal('liveintent.com'); + expect(post.user.ext.tpid.uid).to.equal('0000-1111-2222-3333'); + expect(post.rp).that.is.an('object'); + expect(post.rp.target).that.is.an('object'); + expect(post.rp.target.LIseg).that.is.an('array'); + expect(post.rp.target.LIseg[0]).to.equal('segA'); + expect(post.rp.target.LIseg[1]).to.equal('segB'); expect(post.regs.ext.gdpr).to.equal(1); expect(post).to.have.property('ext').that.is.an('object'); expect(post.ext.prebid.targeting.includewinners).to.equal(true); From ef02b31d4d169b9a0aad91040ddec48b4dd5c93c Mon Sep 17 00:00:00 2001 From: ACannuniRP <57228257+ACannuniRP@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:41:16 +0000 Subject: [PATCH 362/436] Rubicon Adapter: Add multiple sizes to sizeMap (#4407) --- modules/rubiconBidAdapter.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 39a57060ba8..998f4826ead 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -44,6 +44,7 @@ var sizeMap = { 39: '750x100', 40: '750x200', 41: '750x300', + 42: '2x4', 43: '320x50', 44: '300x50', 48: '300x300', @@ -88,8 +89,11 @@ var sizeMap = { 199: '640x200', 213: '1030x590', 214: '980x360', + 221: '1x1', 229: '320x180', 232: '580x400', + 234: '6x6', + 251: '2x2', 257: '400x600', 264: '970x1000', 265: '1920x1080', From 4baaf277e7b771281609f24fb679e44c2ce21607 Mon Sep 17 00:00:00 2001 From: Hugo Duthil Date: Mon, 4 Nov 2019 15:39:19 +0100 Subject: [PATCH 363/436] Add Utils to remove item in LocalStorage (#4355) --- src/utils.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/utils.js b/src/utils.js index 2caaedc4164..ff7ba3b796f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1264,6 +1264,12 @@ export function getDataFromLocalStorage(key) { } } +export function removeDataFromLocalStorage(key) { + if (hasLocalStorage()) { + window.localStorage.removeItem(key); + } +} + export function hasLocalStorage() { try { return !!window.localStorage; From f21599193585405efeaed358ff1dd1aeac451ab0 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 4 Nov 2019 08:20:28 -0800 Subject: [PATCH 364/436] Making originalCpm and originalCurrency fields in bid object always available (#4396) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * moving originalCurrency declaration from currency to bidderFactory * added a comment * trying to re-run the CI job * added unit test case * trying to re-run the CI job --- modules/currency.js | 3 --- src/adapters/bidderFactory.js | 3 +++ test/spec/unit/core/bidderFactory_spec.js | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/currency.js b/modules/currency.js index ae2f9ac1f1b..28e033fb1a2 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -185,9 +185,6 @@ export function addBidResponseHook(fn, adUnitCode, bid) { return (parseFloat(this.cpm) * getCurrencyConversion(this.currency, toCurrency)).toFixed(3); }; - bid.originalCpm = bid.cpm; - bid.originalCurrency = bid.currency; - // execute immediately if the bid is already in the desired currency if (bid.currency === adServerCurrency) { return fn.call(this, adUnitCode, bid); diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 4ccbfd89457..d97bac201ea 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -301,6 +301,9 @@ export function newBidder(spec) { function addBidUsingRequestMap(bid) { const bidRequest = bidRequestMap[bid.requestId]; if (bidRequest) { + // creating a copy of original values as cpm and currency are modified later + bid.originalCpm = bid.cpm; + bid.originalCurrency = bid.currency; const prebidBid = Object.assign(createBid(CONSTANTS.STATUS.GOOD, bidRequest), bid); addBidWithCode(bidRequest.adUnitCode, prebidBid); } else { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index fd54d2911e1..2dcb26061bd 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -364,6 +364,10 @@ describe('bidders created by newBidder', function () { expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + let bidObject = addBidResponseStub.firstCall.args[1]; + // checking the fields added by our code + expect(bidObject.originalCpm).to.equal(bid.cpm); + expect(bidObject.originalCurrency).to.equal(bid.currency); expect(doneStub.calledOnce).to.equal(true); expect(logErrorSpy.callCount).to.equal(0); }); From 422ba3e16779897641a499f29023fda7ba7b9c12 Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Mon, 4 Nov 2019 22:09:52 +0530 Subject: [PATCH 365/436] Placement and inventory (#4353) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json * adding schain object * adding tagid * syntaxx error fix * video.html * space trailing * space * tagid * inventoryId and placement * rewarded video * added unit test case * inventory_id and placement * removed unnecessary file * lint error * Update oneVideoBidAdapter.js * lint error fix --- modules/oneVideoBidAdapter.js | 5 +- modules/oneVideoBidAdapter.md | 73 ++++++++++---------- test/spec/modules/oneVideoBidAdapter_spec.js | 19 +++-- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 80084a0d9ce..99d976e9efe 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -191,7 +191,10 @@ function getRequestData(bid, consentData) { bidData.imp[0].video.playbackmethod = bid.params.video.playbackmethod } if (bid.params.video.placement) { - bidData.imp[0].ext.placement = bid.params.video.placement + bidData.imp[0].video.placement = bid.params.video.placement + } + if (bid.params.video.inventoryid) { + bidData.imp[0].ext.inventoryid = bid.params.video.inventoryid } if (bid.params.video.rewarded) { bidData.imp[0].ext.rewarded = bid.params.video.rewarded diff --git a/modules/oneVideoBidAdapter.md b/modules/oneVideoBidAdapter.md index a626a30eb60..145af1a6fb9 100644 --- a/modules/oneVideoBidAdapter.md +++ b/modules/oneVideoBidAdapter.md @@ -2,7 +2,7 @@ **Module Name**: One Video Bidder Adapter **Module Type**: Bidder Adapter -**Maintainer**: ankur.modi@oath.com +**Maintainer**: deepthi.neeladri.sravana@verizonmedia.com # Description @@ -12,40 +12,43 @@ Connects to One Video demand source to fetch bids. # Test Parameters for Video ``` 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: [1], - position: 1, - delivery: [2], - playbackmethod: [1,5], - sid: , - rewarded: 1 - }, - site: { - id: 1, - page: 'http://abhi12345.com', - referrer: 'http://abhi12345.com' - }, - pubId: 'brxd' - } - } - ] - } + + { + 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], + playbackmethod: [1,5], + sid: , + rewarded: 1, + placement: 1, + inventoryid: 123 + }, + site: { + id: 1, + page: 'http://abhi12345.com', + referrer: 'http://abhi12345.com' + }, + pubId: 'brxd' + } + } + ] + } ] ``` # Test Parameters for banner request diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 6597a4d87c0..1de413ae596 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -30,9 +30,10 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123, sid: 134, - rewarded: 1 + rewarded: 1, + placement: 1, + inventoryid: 123 }, site: { id: 1, @@ -67,9 +68,10 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123, sid: 134, - rewarded: 1 + rewarded: 1, + placement: 1, + inventoryid: 123 } }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); @@ -85,9 +87,10 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123, sid: 134, - rewarded: 1 + rewarded: 1, + placement: 1, + inventoryid: 123 }, pubId: 'brxd' }; @@ -118,11 +121,13 @@ describe('OneVideoBidAdapter', function () { const [ width, height ] = bidRequest.sizes; const placement = bidRequest.params.video.placement; const rewarded = bidRequest.params.video.rewarded; + const inventoryid = bidRequest.params.video.inventoryid; expect(data.imp[0].video.w).to.equal(width); expect(data.imp[0].video.h).to.equal(height); - expect(data.imp[0].ext.placement).to.equal(placement); expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); expect(data.imp[0].ext.rewarded).to.equal(rewarded); + expect(data.imp[0].video.placement).to.equal(placement); + expect(data.imp[0].ext.inventoryid).to.equal(inventoryid); }); it('must parse bid size from a nested array', function () { From 80bbe53907bb0c0a21c73c18a01f9beb53ab3c57 Mon Sep 17 00:00:00 2001 From: hbanalytics <55453525+hbanalytics@users.noreply.github.com> Date: Mon, 4 Nov 2019 21:09:37 +0200 Subject: [PATCH 366/436] Fixes for Platform One Analytics Adapter (#4359) * Added Y1 Analytics Adapter * rename y1AnalyticsAdapter in yieldoneAnalyticsAdapter * Yieldone Bid Adapter: fixes from lint check * Yieldone Analytics Adapter: fix endpoint protocol * Added spec file for yieldone Analytics Adapter * Add adUnitName to analytics data for Yieldone Analytics Adapter * Fix yieldone Analytics Adapter to log only id from adUnitPath * Fix bug with timeout event in Yieldone Analytics Adapter --- modules/yieldoneAnalyticsAdapter.js | 49 ++++++++++++++++++- .../modules/yieldoneAnalyticsAdapter_spec.js | 16 +++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/modules/yieldoneAnalyticsAdapter.js b/modules/yieldoneAnalyticsAdapter.js index 94dd0daa0b2..dec14ff5d0f 100644 --- a/modules/yieldoneAnalyticsAdapter.js +++ b/modules/yieldoneAnalyticsAdapter.js @@ -18,6 +18,49 @@ let currentAuctionId = ''; let url = defaultUrl; let pubId = ''; +function makeAdUnitNameMap() { + if (window.googletag && window.googletag.pubads) { + const p = googletag.pubads(); + if (p && p.getSlots) { + const slots = p.getSlots(); + if (slots && slots.length) { + const map = {}; + slots.forEach((slot) => { + const id = slot.getSlotElementId(); + const name = (slot.getAdUnitPath() || '').split('/').pop(); + map[id] = name; + }); + return map; + } + } + } +} + +function addAdUnitNameForArray(ar, map) { + if (utils.isArray(ar)) { + ar.forEach((it) => { addAdUnitName(it, map) }); + } +} + +function addAdUnitName(params, map) { + if (params.adUnitCode && map[params.adUnitCode]) { + params.adUnitName = map[params.adUnitCode]; + } + if (utils.isArray(params.adUnits)) { + params.adUnits.forEach((adUnit) => { + if (adUnit.code && map[adUnit.code]) { + adUnit.name = map[adUnit.code]; + } + }); + } + if (utils.isArray(params.adUnitCodes)) { + params.adUnitNames = params.adUnitCodes.map((code) => map[code]); + } + ['bids', 'bidderRequests', 'bidsReceived', 'noBids'].forEach((it) => { + addAdUnitNameForArray(params[it], map); + }); +} + const yieldoneAnalytics = Object.assign(adapter({analyticsType}), { getUrl() { return url; }, track({eventType, args = {}}) { @@ -36,7 +79,7 @@ const yieldoneAnalytics = Object.assign(adapter({analyticsType}), { const reqBidId = `${bid.bidId}_${bid.auctionId}`; const reqBidderId = `${bid.bidder}_${bid.auctionId}`; if (!eventsStorage[bid.auctionId]) eventsStorage[bid.auctionId] = []; - if (requestedBidders[reqBidderId] && requestedBids[reqBidId]) { + if ((requestedBidders[reqBidderId] || reqBidders[bid.bidder]) && requestedBids[reqBidId]) { if (!reqBidders[bid.bidder]) { reqBidders[bid.bidder] = requestedBidders[reqBidderId]; reqBidders[bid.bidder].pubId = pubId; @@ -73,6 +116,10 @@ const yieldoneAnalytics = Object.assign(adapter({analyticsType}), { if (yieldoneAnalytics.eventsStorage[args.auctionId]) { yieldoneAnalytics.eventsStorage[args.auctionId].forEach((it) => { it.page = {url: referrers[currentAuctionId]}; + const adUnitNameMap = makeAdUnitNameMap(); + if (adUnitNameMap) { + addAdUnitName(it.params, adUnitNameMap); + } }); } yieldoneAnalytics.sendStat(yieldoneAnalytics.eventsStorage[args.auctionId], args.auctionId); diff --git a/test/spec/modules/yieldoneAnalyticsAdapter_spec.js b/test/spec/modules/yieldoneAnalyticsAdapter_spec.js index a297403b2e0..b7b4cd82b07 100644 --- a/test/spec/modules/yieldoneAnalyticsAdapter_spec.js +++ b/test/spec/modules/yieldoneAnalyticsAdapter_spec.js @@ -97,6 +97,15 @@ describe('Yieldone Prebid Analytic', function () { mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, params: {param_1: '111', param_2: '222'}, sizes: [[300, 250], [336, 280]] + }, + { + adUnitCode: '0000', + auctionId: auctionId, + bidId: '14151', + bidder: 'biddertest_3', + mediaTypes: {banner: {sizes: [[300, 250], [336, 280]]}}, + params: {param_1: '333', param_2: '222'}, + sizes: [[300, 250], [336, 280]] } ] } @@ -140,6 +149,11 @@ describe('Yieldone Prebid Analytic', function () { bidId: '12131', auctionId: auctionId, bidder: 'biddertest_3' + }, + { + bidId: '14151', + auctionId: auctionId, + bidder: 'biddertest_3' } ]; @@ -234,7 +248,7 @@ describe('Yieldone Prebid Analytic', function () { events.emit(constants.EVENTS.BID_RESPONSE, responses[1]); events.emit(constants.EVENTS.BID_RESPONSE, responses[2]); - events.emit(constants.EVENTS.BID_TIMEOUT, [responses[3]]); + events.emit(constants.EVENTS.BID_TIMEOUT, [responses[3], responses[4]]); events.emit(constants.EVENTS.AUCTION_END, {auctionId: auctionId}); From ab6af4c21f3ca965f82b5a22f656786189a21b7d Mon Sep 17 00:00:00 2001 From: skazedo Date: Mon, 4 Nov 2019 16:00:18 -0500 Subject: [PATCH 367/436] Added protocol to url (#4395) * initial commit * updated contact and tag details * changes ti support the renderers * changes to pass dimId * fixed names of internal mapping * added comment * added gdpr param to request and other fixes * modified api url * fix * fixed the secure api call * rolled back video event callback till we support it * updated doc with video details * added bid won and timeout pixel * added testcase for bid events * modified testcase * fixed the url logged * tag param values passed ot renderer * added a conditioal check * changes to support new param to adserver for purpose of tracking * passed param to renderer * missing variable defined * added protocol to url * fixed test for protocol * changed urls to secure only --- modules/zedoBidAdapter.js | 15 +- test/spec/modules/zedoBidAdapter_spec.js | 708 +++++++++++------------ 2 files changed, 360 insertions(+), 363 deletions(-) diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index b09913ecf60..64d28f3f1c6 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -6,8 +6,7 @@ import { Renderer } from '../src/Renderer'; import * as url from '../src/url'; const BIDDER_CODE = 'zedo'; -const URL = '//z2.zedo.com/asw/fmh.json'; -const SECURE_URL = '//saxp.zedo.com/asw/fmh.json'; +const SECURE_URL = 'https://saxp.zedo.com/asw/fmh.json'; const DIM_TYPE = { '7': 'display', '9': 'display', @@ -23,7 +22,6 @@ const DIM_TYPE = { '103': 'display' // '85': 'pre-mid-post-roll', }; -const EVENT_PIXEL_URL = 'm1.zedo.com/log/p.gif'; const SECURE_EVENT_PIXEL_URL = 'tt1.zedo.com/log/p.gif'; export const spec = { @@ -86,10 +84,9 @@ export const spec = { } data['placements'].push(placement); }); - let reqUrl = utils.getTopWindowLocation().protocol === 'http:' ? URL : SECURE_URL; return { method: 'GET', - url: reqUrl, + url: SECURE_URL, data: 'g=' + JSON.stringify(data) } }, @@ -127,7 +124,7 @@ export const spec = { 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'; + let url = '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') { @@ -194,7 +191,7 @@ function newBid(serverBid, creativeBid, bidderRequest) { bidderRequest, 'renderer.options' ); - let rendererUrl = utils.getTopWindowLocation().protocol === 'http:' ? 'http://c14.zedo.com/gecko/beta/fmpbgt.min.js' : 'https://ss3.zedo.com/gecko/beta/fmpbgt.min.js'; + let rendererUrl = 'https://ss3.zedo.com/gecko/beta/fmpbgt.min.js'; Object.assign(bid, { adResponse: serverBid, renderer: getRenderer(bid.adUnitCode, serverBid.slotId, rendererUrl, rendererOptions) @@ -279,8 +276,8 @@ function parseMediaType(creativeBid) { function logEvent(eid, data) { let getParams = { - protocol: utils.getTopWindowLocation().protocol === 'http:' ? 'http' : 'https', - hostname: utils.getTopWindowLocation().protocol === 'http:' ? EVENT_PIXEL_URL : SECURE_EVENT_PIXEL_URL, + protocol: 'https', + hostname: SECURE_EVENT_PIXEL_URL, search: getLoggingData(eid, data) }; utils.triggerPixel(url.format(getParams).replace(/&/g, ';')); diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js index 76301ba9018..f6702e6f459 100644 --- a/test/spec/modules/zedoBidAdapter_spec.js +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -1,354 +1,354 @@ -import { expect } from 'chai'; -import { spec } from 'modules/zedoBidAdapter'; - -describe('The ZEDO bidding adapter', function () { - describe('isBidRequestValid', function () { - it('should return false when given an invalid bid', function () { - const bid = { - bidder: 'zedo', - }; - const isValid = spec.isBidRequestValid(bid); - expect(isValid).to.equal(false); - }); - - it('should return true when given a channelcode bid', function () { - const bid = { - bidder: 'zedo', - params: { - channelCode: 20000000, - dimId: 9 - }, - }; - const isValid = spec.isBidRequestValid(bid); - expect(isValid).to.equal(true); - }); - }); - - describe('buildRequests', function () { - const bidderRequest = { - timeout: 3000, - }; - - it('should properly build a channelCode request for dim Id with type not defined', function () { - const bidRequests = [ - { - bidder: 'zedo', - adUnitCode: 'p12345', - transactionId: '12345667', - sizes: [[300, 200]], - params: { - channelCode: 20000000, - dimId: 10, - pubId: 1 - }, - }, - ]; - const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/saxp.zedo.com\/asw\/fmh.json/); - expect(request.method).to.equal('GET'); - const zedoRequest = request.data; - expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":1,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); - }); - - it('should properly build a channelCode request for video with type defined', function () { - 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(/^\/\/saxp.zedo.com\/asw\/fmh.json/); - expect(request.method).to.equal('GET'); - const zedoRequest = request.data; - expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); - }); - - describe('buildGDPRRequests', function () { - let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; - const bidderRequest = { - timeout: 3000, - gdprConsent: { - 'consentString': consentString, - 'gdprApplies': true - } - }; - - it('should properly build request with gdpr consent', function () { - 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,"publisher":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}],"gdpr":1,"gdpr_consent":"BOJ8RZsOJ8RZsABAB8AAAAAZ+A=="}'); - }); - }); - }); - describe('interpretResponse', function () { - it('should return an empty array when there is bid response', function () { - const response = {}; - const request = { bidRequests: [] }; - const bids = spec.interpretResponse(response, request); - expect(bids).to.have.lengthOf(0); - }); - - it('should properly parse a bid response with no valid creative', function () { - 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', function () { - 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', function () { - 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].adType).to.equal('VAST'); - expect(bids[0].vastXml).to.not.equal(''); - expect(bids[0].ad).to.be.an('undefined'); - expect(bids[0].renderer).not.to.be.an('undefined'); - }); - }); - - describe('user sync', function () { - it('should register the iframe sync url', function () { - let syncs = spec.getUserSyncs({ - iframeEnabled: true - }); - expect(syncs).to.not.be.an('undefined'); - expect(syncs).to.have.lengthOf(1); - expect(syncs[0].type).to.equal('iframe'); - }); - - it('should pass gdpr params', function () { - 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'); - }); - }); - - describe('bid events', function () { - it('should trigger a win pixel', function () { - const bid = { - 'bidderCode': 'zedo', - 'width': '300', - 'height': '250', - 'statusMessage': 'Bid available', - 'adId': '148018fe5e', - 'cpm': 0.5, - 'ad': 'dummy data', - 'ad_id': '12345', - 'sizeId': '15', - 'adResponse': - { - 'creatives': [ - { - 'adId': '12345', - 'height': '480', - 'width': '640', - 'isFoc': true, - 'creativeDetails': { - 'type': 'VAST', - 'adContent': '' - }, - 'seeder': { - 'network': 1234, - 'servedChan': 1234567, - }, - 'cpm': '1200000', - 'servedChan': 1234, - }] - }, - 'params': [{ - 'channelCode': '123456', - 'dimId': '85' - }], - 'requestTimestamp': 1540401686, - 'responseTimestamp': 1540401687, - 'timeToRespond': 6253, - 'pbLg': '0.50', - 'pbMg': '0.50', - 'pbHg': '0.53', - 'adUnitCode': '/123456/header-bid-tag-0', - 'bidder': 'zedo', - 'size': '300x250', - 'adserverTargeting': { - 'hb_bidder': 'zedo', - 'hb_adid': '148018fe5e', - 'hb_pb': '10.00', - } - }; - spec.onBidWon(bid); - spec.onTimeout(bid); - }); - it('should trigger a timeout pixel', function () { - const bid = { - 'bidderCode': 'zedo', - 'width': '300', - 'height': '250', - 'statusMessage': 'Bid available', - 'adId': '148018fe5e', - 'cpm': 0.5, - 'ad': 'dummy data', - 'ad_id': '12345', - 'sizeId': '15', - 'params': [{ - 'channelCode': '123456', - 'dimId': '85' - }], - 'timeout': 1, - 'requestTimestamp': 1540401686, - 'responseTimestamp': 1540401687, - 'timeToRespond': 6253, - 'adUnitCode': '/123456/header-bid-tag-0', - 'bidder': 'zedo', - 'size': '300x250', - }; - spec.onBidWon(bid); - spec.onTimeout(bid); - }); - }); -}); +import { expect } from 'chai'; +import { spec } from 'modules/zedoBidAdapter'; + +describe('The ZEDO bidding adapter', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { + const bid = { + bidder: 'zedo', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + + it('should return true when given a channelcode bid', function () { + const bid = { + bidder: 'zedo', + params: { + channelCode: 20000000, + dimId: 9 + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidderRequest = { + timeout: 3000, + }; + + it('should properly build a channelCode request for dim Id with type not defined', function () { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [[300, 200]], + params: { + channelCode: 20000000, + dimId: 10, + pubId: 1 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^https:\/\/saxp.zedo.com\/asw\/fmh.json/); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":1,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); + }); + + it('should properly build a channelCode request for video with type defined', function () { + 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(/^https:\/\/saxp.zedo.com\/asw\/fmh.json/); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"publisher":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); + }); + + describe('buildGDPRRequests', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + const bidderRequest = { + timeout: 3000, + gdprConsent: { + 'consentString': consentString, + 'gdprApplies': true + } + }; + + it('should properly build request with gdpr consent', function () { + 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,"publisher":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}],"gdpr":1,"gdpr_consent":"BOJ8RZsOJ8RZsABAB8AAAAAZ+A=="}'); + }); + }); + }); + describe('interpretResponse', function () { + it('should return an empty array when there is bid response', function () { + const response = {}; + const request = { bidRequests: [] }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response with no valid creative', function () { + 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', function () { + 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', function () { + 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].adType).to.equal('VAST'); + expect(bids[0].vastXml).to.not.equal(''); + expect(bids[0].ad).to.be.an('undefined'); + expect(bids[0].renderer).not.to.be.an('undefined'); + }); + }); + + describe('user sync', function () { + it('should register the iframe sync url', function () { + let syncs = spec.getUserSyncs({ + iframeEnabled: true + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + }); + + it('should pass gdpr params', function () { + 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'); + }); + }); + + describe('bid events', function () { + it('should trigger a win pixel', function () { + const bid = { + 'bidderCode': 'zedo', + 'width': '300', + 'height': '250', + 'statusMessage': 'Bid available', + 'adId': '148018fe5e', + 'cpm': 0.5, + 'ad': 'dummy data', + 'ad_id': '12345', + 'sizeId': '15', + 'adResponse': + { + 'creatives': [ + { + 'adId': '12345', + 'height': '480', + 'width': '640', + 'isFoc': true, + 'creativeDetails': { + 'type': 'VAST', + 'adContent': '' + }, + 'seeder': { + 'network': 1234, + 'servedChan': 1234567, + }, + 'cpm': '1200000', + 'servedChan': 1234, + }] + }, + 'params': [{ + 'channelCode': '123456', + 'dimId': '85' + }], + 'requestTimestamp': 1540401686, + 'responseTimestamp': 1540401687, + 'timeToRespond': 6253, + 'pbLg': '0.50', + 'pbMg': '0.50', + 'pbHg': '0.53', + 'adUnitCode': '/123456/header-bid-tag-0', + 'bidder': 'zedo', + 'size': '300x250', + 'adserverTargeting': { + 'hb_bidder': 'zedo', + 'hb_adid': '148018fe5e', + 'hb_pb': '10.00', + } + }; + spec.onBidWon(bid); + spec.onTimeout(bid); + }); + it('should trigger a timeout pixel', function () { + const bid = { + 'bidderCode': 'zedo', + 'width': '300', + 'height': '250', + 'statusMessage': 'Bid available', + 'adId': '148018fe5e', + 'cpm': 0.5, + 'ad': 'dummy data', + 'ad_id': '12345', + 'sizeId': '15', + 'params': [{ + 'channelCode': '123456', + 'dimId': '85' + }], + 'timeout': 1, + 'requestTimestamp': 1540401686, + 'responseTimestamp': 1540401687, + 'timeToRespond': 6253, + 'adUnitCode': '/123456/header-bid-tag-0', + 'bidder': 'zedo', + 'size': '300x250', + }; + spec.onBidWon(bid); + spec.onTimeout(bid); + }); + }); +}); From e5d06663621961daa82e2cd401be996bab5d3cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=9B=A8=E8=BB=92=20=D0=9F=D0=B5=D1=82=D1=80?= Date: Mon, 4 Nov 2019 22:16:47 +0100 Subject: [PATCH 368/436] Update emoteev endpoints (#4329) --- modules/emoteevBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/emoteevBidAdapter.js b/modules/emoteevBidAdapter.js index db84b6ea36d..fb62e4381e3 100644 --- a/modules/emoteevBidAdapter.js +++ b/modules/emoteevBidAdapter.js @@ -36,8 +36,8 @@ export const BIDDER_CODE = 'emoteev'; */ export const ADAPTER_VERSION = '1.35.0'; -export const DOMAIN = 'prebid.emoteev.io'; -export const DOMAIN_STAGING = 'prebid-staging.emoteev.io'; +export const DOMAIN = 'prebid.emoteev.xyz'; +export const DOMAIN_STAGING = 'prebid-staging.emoteev.xyz'; export const DOMAIN_DEVELOPMENT = 'localhost:3000'; /** From 353a3cec6f94573e089318c423fd21604e8cff1e Mon Sep 17 00:00:00 2001 From: Konrad Dulemba Date: Mon, 4 Nov 2019 22:23:45 +0100 Subject: [PATCH 369/436] JustPremium: Update to Prebid 3.0 (#4410) --- modules/justpremiumBidAdapter.js | 13 ++++++------- modules/justpremiumBidAdapter.md | 12 ++++++++++-- test/spec/modules/justpremiumBidAdapter_spec.js | 8 ++++---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 68b73c333ca..f336d44671b 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -2,8 +2,8 @@ import { registerBidder } from '../src/adapters/bidderFactory' import { deepAccess } from '../src/utils'; const BIDDER_CODE = 'justpremium' -const ENDPOINT_URL = '//pre.ads.justpremium.com/v/2.0/t/xhr' -const JP_ADAPTER_VERSION = '1.4' +const ENDPOINT_URL = 'https://pre.ads.justpremium.com/v/2.0/t/xhr' +const JP_ADAPTER_VERSION = '1.5' const pixels = [] const TRACK_START_TIME = Date.now() let LAST_PAYLOAD = {} @@ -44,7 +44,7 @@ export const spec = { const zone = b.params.zone const sizes = payload.sizes sizes[zone] = sizes[zone] || [] - sizes[zone].push.apply(sizes[zone], b.sizes) + sizes[zone].push.apply(sizes[zone], b.mediaTypes && b.mediaTypes.banner && b.mediaTypes.banner.sizes) }) if (deepAccess(validBidRequests[0], 'userId.pubcid')) { @@ -85,7 +85,7 @@ export const spec = { bidRequests.bids.forEach(adUnit => { let bid = findBid(adUnit.params, body.bid) if (bid) { - let size = (adUnit.sizes && adUnit.sizes.length && adUnit.sizes[0]) || [] + let size = (adUnit.mediaTypes && adUnit.mediaTypes.banner && adUnit.mediaTypes.banner.sizes && adUnit.mediaTypes.banner.sizes.length && adUnit.mediaTypes.banner.sizes[0]) || [] let bidResponse = { requestId: adUnit.bidId, creativeId: bid.id, @@ -101,12 +101,11 @@ export const spec = { bidResponses.push(bidResponse) } }) - return bidResponses }, getUserSyncs: function getUserSyncs(syncOptions, responses, gdprConsent) { - let url = '//pre.ads.justpremium.com/v/1.0/t/sync' + '?_c=' + 'a' + Math.random().toString(36).substring(7) + Date.now(); + let url = 'https://pre.ads.justpremium.com/v/1.0/t/sync' + '?_c=' + 'a' + Math.random().toString(36).substring(7) + Date.now(); if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { url = url + '&consentString=' + encodeURIComponent(gdprConsent.consentString) } @@ -159,7 +158,7 @@ function track (data, payload, type) { let duration = Date.now() - TRACK_START_TIME - const pixelUrl = `//emea-v3.tracking.justpremium.com/tracking.gif?rid=&sid=&uid=&vr=& + const pixelUrl = `https://emea-v3.tracking.justpremium.com/tracking.gif?rid=&sid=&uid=&vr=& ru=${encodeURIComponent(pubUrl)}&tt=&siw=&sh=${payload.sh}&sw=${payload.sw}&wh=${payload.wh}&ww=${payload.ww}&an=&vn=& sd=&_c=&et=&aid=&said=&ei=&fc=&sp=&at=bidder&cid=&ist=&mg=&dl=&dlt=&ev=&vt=&zid=${payload.id}&dr=${duration}&di=&pr=& cw=&ch=&nt=&st=&jp=${encodeURIComponent(JSON.stringify(jp))}&ty=${type}` diff --git a/modules/justpremiumBidAdapter.md b/modules/justpremiumBidAdapter.md index c3e17abfec5..45dcb7b7f99 100644 --- a/modules/justpremiumBidAdapter.md +++ b/modules/justpremiumBidAdapter.md @@ -12,7 +12,11 @@ To get more information or your unique zone id please contact Justpremium. ``` var adUnits = [ { - sizes: [[1, 1]], + mediaTypes: { + banner: { + sizes: [[1, 1]] + } + }, code: 'div-gpt-ad-1471513102552-0', bids: [ { @@ -25,7 +29,11 @@ To get more information or your unique zone id please contact Justpremium. ] }, { - sizes: [[300, 600]], + mediaTypes: { + banner: { + sizes: [[300, 600]] + } + }, code: 'div-gpt-ad-1471513102552-1', bids: [ { diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index c3cd015b6e3..503ca1e3d81 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -47,7 +47,7 @@ describe('justpremium adapter', function () { let bidderRequest = { refererInfo: { - referer: 'http://justpremium.com' + referer: 'https://justpremium.com' } } @@ -73,16 +73,16 @@ describe('justpremium adapter', function () { const jpxRequest = JSON.parse(request.data) expect(jpxRequest).to.not.equal(null) expect(jpxRequest.zone).to.not.equal('undefined') - expect(bidderRequest.refererInfo.referer).to.equal('http://justpremium.com') + expect(bidderRequest.refererInfo.referer).to.equal('https://justpremium.com') expect(jpxRequest.sw).to.equal(window.top.screen.width) expect(jpxRequest.sh).to.equal(window.top.screen.height) expect(jpxRequest.ww).to.equal(window.top.innerWidth) expect(jpxRequest.wh).to.equal(window.top.innerHeight) expect(jpxRequest.c).to.not.equal('undefined') expect(jpxRequest.id).to.equal(adUnits[0].params.zone) - expect(jpxRequest.sizes).to.not.equal('undefined') + expect(jpxRequest.mediaTypes && jpxRequest.mediaTypes.banner && jpxRequest.mediaTypes.banner.sizes).to.not.equal('undefined') expect(jpxRequest.version.prebid).to.equal('$prebid.version$') - expect(jpxRequest.version.jp_adapter).to.equal('1.4') + expect(jpxRequest.version.jp_adapter).to.equal('1.5') expect(jpxRequest.pubcid).to.equal('0000000') expect(jpxRequest.uids.tdid).to.equal('1111111') expect(jpxRequest.uids.id5id).to.equal('2222222') From b167c2997741012a5aa3f56bfbb16ac5ca500d4f Mon Sep 17 00:00:00 2001 From: Mariya Mego <31904600+mash-a@users.noreply.github.com> Date: Mon, 4 Nov 2019 16:46:41 -0800 Subject: [PATCH 370/436] Update underdogmedia adapter for pbjs 3.0 (#4390) * Update underdogmedia adapter for pbjs 3.0 * Ensure request to endpoint is secure * Update prebid version * Lint fix --- modules/underdogmediaBidAdapter.js | 16 +++--- modules/underdogmediaBidAdapter.md | 6 ++- .../modules/underdogmediaBidAdapter_spec.js | 54 +++++++++++++++---- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index 534b77db3b1..03c815ab005 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -2,17 +2,19 @@ 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.13V'; +const UDM_ADAPTER_VERSION = '3.0V'; const UDM_VENDOR_ID = '159'; +const prebidVersion = '$prebid.version$'; -utils.logMessage(`Initializing UDM Adapter. PBJS Version: ${$$PREBID_GLOBAL$$.version} with adapter version: ${UDM_ADAPTER_VERSION} Updated 20180604`); +utils.logMessage(`Initializing UDM Adapter. PBJS Version: ${prebidVersion} with adapter version: ${UDM_ADAPTER_VERSION} Updated 20191028`); export const spec = { code: BIDDER_CODE, bidParams: [], isBidRequestValid: function (bid) { - return !!((bid.params && bid.params.siteId) && (bid.sizes && bid.sizes.length > 0)); + const bidSizes = bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes ? bid.mediaTypes.banner.sizes : bid.sizes; + return !!((bid.params && bid.params.siteId) && (bidSizes && bidSizes.length > 0)); }, buildRequests: function (validBidRequests, bidderRequest) { @@ -20,7 +22,8 @@ export const spec = { var siteId = 0; validBidRequests.forEach(bidParam => { - sizes = utils.flatten(sizes, utils.parseSizesInput(bidParam.sizes)); + let bidParamSizes = bidParam.mediaTypes && bidParam.mediaTypes.banner && bidParam.mediaTypes.banner.sizes ? bidParam.mediaTypes.banner.sizes : bidParam.sizes; + sizes = utils.flatten(sizes, utils.parseSizesInput(bidParamSizes)); siteId = bidParam.params.siteId; }); @@ -47,7 +50,7 @@ export const spec = { if (!data.gdprApplies || data.consentGiven) { return { method: 'GET', - url: `${window.location.protocol}//udmserve.net/udm/img.fetch`, + url: 'https://udmserve.net/udm/img.fetch', data: data, bidParams: validBidRequests }; @@ -67,7 +70,8 @@ export const spec = { } var sizeNotFound = true; - utils.parseSizesInput(bidParam.sizes).forEach(size => { + const bidParamSizes = bidParam.mediaTypes && bidParam.mediaTypes.banner && bidParam.mediaTypes.banner.sizes ? bidParam.mediaTypes.banner.sizes : bidParam.sizes + utils.parseSizesInput(bidParamSizes).forEach(size => { if (size === mid.width + 'x' + mid.height) { sizeNotFound = false; } diff --git a/modules/underdogmediaBidAdapter.md b/modules/underdogmediaBidAdapter.md index f652e2fcbbf..ac7434da482 100644 --- a/modules/underdogmediaBidAdapter.md +++ b/modules/underdogmediaBidAdapter.md @@ -13,7 +13,11 @@ Module that connects to Underdog Media's servers to fetch bids. var adUnits = [ { code: 'test-div', - sizes: [[300, 250]], // a display size + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, bids: [ { bidder: "underdogmedia", diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js index 6f4df57d316..68d6c985450 100644 --- a/test/spec/modules/underdogmediaBidAdapter_spec.js +++ b/test/spec/modules/underdogmediaBidAdapter_spec.js @@ -13,7 +13,11 @@ describe('UnderdogMedia adapter', function () { siteId: 12143 }, adUnitCode: '/19968336/header-bid-tag-1', - sizes: [[300, 250], [300, 600], [728, 90], [160, 600], [320, 50]], + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600], [728, 90], [160, 600], [320, 50]], + } + }, bidId: '23acc48ad47af5', auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', bidderRequestId: '1c56ad30b9b8ca8', @@ -43,7 +47,11 @@ describe('UnderdogMedia adapter', function () { params: { siteId: '12143' }, - sizes: [[300, 250], [300, 600]] + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + } }; const isValid = spec.isBidRequestValid(validBid); @@ -66,7 +74,11 @@ describe('UnderdogMedia adapter', function () { let invalidBid = { bidder: 'underdogmedia', params: {}, - sizes: [[300, 250], [300, 600]] + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + } }; const isValid = spec.isBidRequestValid(invalidBid); @@ -77,8 +89,12 @@ describe('UnderdogMedia adapter', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', - sizes: [[300, 250]], bidder: 'underdogmedia', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, params: { siteId: '12143' }, @@ -95,7 +111,11 @@ describe('UnderdogMedia adapter', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, bidder: 'underdogmedia', params: { siteId: '12143' @@ -113,7 +133,11 @@ describe('UnderdogMedia adapter', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, bidder: 'underdogmedia', params: { siteId: '12143' @@ -133,7 +157,11 @@ describe('UnderdogMedia adapter', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, bidder: 'underdogmedia', params: { siteId: '12143' @@ -164,7 +192,11 @@ describe('UnderdogMedia adapter', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, bidder: 'underdogmedia', params: { siteId: '12143' @@ -199,7 +231,11 @@ describe('UnderdogMedia adapter', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', - sizes: [[300, 250], [728, 90]], + mediaTypes: { + banner: { + sizes: [[300, 250], [728, 90]] + } + }, bidder: 'underdogmedia', params: { siteId: '12143' From 8acb120ccb32ff0a69485425beab4fb16b9c1390 Mon Sep 17 00:00:00 2001 From: Daniel Cassidy Date: Tue, 5 Nov 2019 06:40:10 +0000 Subject: [PATCH 371/436] Update Consumable adapter for Prebid.js 3.0 (#4401) * Consumable: Clean up tests. * Consumable: Update use of deprecated function. * Consumable: Read sizes from mediaTypes.banner.sizes. * Consumable: Fix lint violation. --- modules/consumableBidAdapter.js | 8 +- .../spec/modules/consumableBidAdapter_spec.js | 218 +++++++++++------- 2 files changed, 145 insertions(+), 81 deletions(-) diff --git a/modules/consumableBidAdapter.js b/modules/consumableBidAdapter.js index d462acaee59..bd24870c5e5 100644 --- a/modules/consumableBidAdapter.js +++ b/modules/consumableBidAdapter.js @@ -47,7 +47,7 @@ export const spec = { const data = Object.assign({ placements: [], time: Date.now(), - url: utils.getTopWindowUrl(), + url: bidderRequest.refererInfo.referer, referrer: document.referrer, source: [{ 'name': 'prebidjs', @@ -63,9 +63,10 @@ export const spec = { } validBidRequests.map(bid => { + const sizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes || []; const placement = Object.assign({ divName: bid.bidId, - adTypes: bid.adTypes || getSize(bid.sizes) + adTypes: bid.adTypes || getSize(sizes) }, bid.params); if (placement.networkId && placement.siteId && placement.unitId && placement.unitName) { @@ -75,6 +76,7 @@ export const spec = { ret.data = JSON.stringify(data); ret.bidRequest = validBidRequests; + ret.bidderRequest = bidderRequest; ret.url = BASE_URI; return ret; @@ -117,7 +119,7 @@ export const spec = { bid.creativeId = decision.adId; bid.ttl = 30; bid.netRevenue = true; - bid.referrer = utils.getTopWindowUrl(); + bid.referrer = bidRequest.bidderRequest.refererInfo.referer; bidResponses.push(bid); } diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index fc5e1d1b45a..7785454f8e1 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -1,58 +1,127 @@ -import { expect } from 'chai'; -import { spec } from 'modules/consumableBidAdapter'; -import { createBid } from 'src/bidfactory'; +import {expect} from 'chai'; +import {spec} from 'modules/consumableBidAdapter'; +import {createBid} from 'src/bidfactory'; const ENDPOINT = 'https://e.serverbid.com/api/v2'; const SMARTSYNC_CALLBACK = 'serverbidCallBids'; -const REQUEST = { - 'bidderCode': 'consumable', - 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d', - 'bidderRequestId': '109f2a181342a9', - 'bidRequest': [{ - 'bidder': 'consumable', - 'params': { - 'networkId': 9969, - 'siteId': 730181, - 'unitId': 123456, - 'unitName': 'cnsmbl-unit' - }, - 'placementCode': 'div-gpt-ad-1487778092495-0', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '2b0f82502298c9', - 'bidderRequestId': '109f2a181342a9', - 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' +const BIDDER_REQUEST_1 = { + bidderCode: 'consumable', + auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + bidRequest: [ + { + bidder: 'consumable', + params: { + networkId: '9969', + siteId: '730181', + unitId: '123456', + unitName: 'cnsmbl-unit' + }, + placementCode: 'header-bid-tag-1', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: '23acc48ad47af5', + auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ], + gdprConsent: { + consentString: 'consent-test', + gdprApplies: false }, - { - 'bidder': 'consumable', - 'params': { - 'networkId': 9969, - 'siteId': 730181, - 'unitId': 123456, - 'unitName': 'cnsmbl-unit' + refererInfo: { + referer: 'http://example.com/page.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' + ] + } +}; + +const BIDDER_REQUEST_2 = { + bidderCode: 'consumable', + auctionId: 'a4713c32-3762-4798-b342-4ab810ca770d', + bidderRequestId: '109f2a181342a9', + bidRequest: [ + { + bidder: 'consumable', + params: { + networkId: 9969, + siteId: 730181, + unitId: 123456, + unitName: 'cnsmbl-unit' + }, + placementCode: 'div-gpt-ad-1487778092495-0', + mediaTypes: { + banner: { + sizes: [ + [728, 90], + [970, 90] + ] + } + }, + bidId: '2b0f82502298c9', + bidderRequestId: '109f2a181342a9', + auctionId: 'a4713c32-3762-4798-b342-4ab810ca770d' }, - 'placementCode': 'div-gpt-ad-1487778092495-0', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '123', - 'bidderRequestId': '109f2a181342a9', - 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' - }], - 'gdprConsent': { - 'consentString': 'consent-test', - 'gdprApplies': true + { + bidder: 'consumable', + params: { + networkId: 9969, + siteId: 730181, + unitId: 123456, + unitName: 'cnsmbl-unit' + }, + placementCode: 'div-gpt-ad-1487778092495-0', + mediaTypes: { + banner: { + sizes: [ + [728, 90], + [970, 90] + ] + } + }, + bidId: '123', + bidderRequestId: '109f2a181342a9', + auctionId: 'a4713c32-3762-4798-b342-4ab810ca770d' + } + ], + gdprConsent: { + consentString: 'consent-test', + gdprApplies: true }, - 'start': 1487883186070, - 'auctionStart': 1487883186069, - 'timeout': 3000 + refererInfo: { + referer: 'http://example.com/page.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' + ] + } }; -const RESPONSE = { +const BIDDER_REQUEST_EMPTY = { + bidderCode: 'consumable', + auctionId: 'b06458ef-4fe5-4a0b-a61b-bccbcedb7b11', + bidderRequestId: '8c8006750b10fd', + bidRequest: [], + gdprConsent: { + consentString: 'consent-test', + gdprApplies: false + } +}; + +const AD_SERVER_RESPONSE = { 'headers': null, 'body': { 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, @@ -108,30 +177,17 @@ const RESPONSE = { } }; +const BUILD_REQUESTS_OUTPUT = { + method: 'POST', + url: 'https://e.serverbid.com/api/v2', + data: '', + bidRequest: BIDDER_REQUEST_2.bidRequest, + bidderRequest: BIDDER_REQUEST_2 +}; + describe('Consumable BidAdapter', function () { - let bidRequests; let adapter = spec; - beforeEach(function () { - bidRequests = [ - { - bidder: 'consumable', - params: { - networkId: '9969', - siteId: '730181', - unitId: '123456', - unitName: 'cnsmbl-unit' - }, - placementCode: 'header-bid-tag-1', - sizes: [[300, 250], [300, 600]], - bidId: '23acc48ad47af5', - auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' - } - ]; - }); - describe('bid request validation', function () { it('should accept valid bid requests', function () { let bid = { @@ -187,43 +243,49 @@ describe('Consumable BidAdapter', function () { describe('buildRequests validation', function () { it('creates request data', function () { - let request = spec.buildRequests(bidRequests); + let request = spec.buildRequests(BIDDER_REQUEST_1.bidRequest, BIDDER_REQUEST_1); expect(request).to.exist.and.to.be.a('object'); }); it('request to consumable should contain a url', function () { - let request = spec.buildRequests(bidRequests); + let request = spec.buildRequests(BIDDER_REQUEST_1.bidRequest, BIDDER_REQUEST_1); expect(request.url).to.have.string('serverbid.com'); }); it('requires valid bids to make request', function () { - let request = spec.buildRequests([]); + let request = spec.buildRequests(BIDDER_REQUEST_EMPTY.bidRequest, BIDDER_REQUEST_EMPTY); expect(request.bidRequest).to.be.empty; }); it('sends bid request to ENDPOINT via POST', function () { - let request = spec.buildRequests(bidRequests); + let request = spec.buildRequests(BIDDER_REQUEST_1.bidRequest, BIDDER_REQUEST_1); expect(request.method).to.have.string('POST'); }); + + it('passes through bidderRequest', function () { + let request = spec.buildRequests(BIDDER_REQUEST_1.bidRequest, BIDDER_REQUEST_1); + + expect(request.bidderRequest).to.equal(BIDDER_REQUEST_1); + }) }); describe('interpretResponse validation', function () { it('response should have valid bidderCode', function () { - let bidRequest = spec.buildRequests(REQUEST.bidRequest, REQUEST); + let bidRequest = spec.buildRequests(BIDDER_REQUEST_2.bidRequest, BIDDER_REQUEST_2); let bid = createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('consumable'); }); it('response should include objects for all bids', function () { - let bids = spec.interpretResponse(RESPONSE, REQUEST); + let bids = spec.interpretResponse(AD_SERVER_RESPONSE, BUILD_REQUESTS_OUTPUT); expect(bids.length).to.equal(2); }); it('registers bids', function () { - let bids = spec.interpretResponse(RESPONSE, REQUEST); + let bids = spec.interpretResponse(AD_SERVER_RESPONSE, BUILD_REQUESTS_OUTPUT); bids.forEach(b => { expect(b).to.have.property('cpm'); expect(b.cpm).to.be.above(0); @@ -243,14 +305,14 @@ describe('Consumable BidAdapter', function () { }); it('handles nobid responses', function () { - let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) - let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); + let EMPTY_RESP = Object.assign({}, AD_SERVER_RESPONSE, {'body': {'decisions': null}}) + let bids = spec.interpretResponse(EMPTY_RESP, BUILD_REQUESTS_OUTPUT); expect(bids).to.be.empty; }); it('handles no server response', function () { - let bids = spec.interpretResponse(null, REQUEST); + let bids = spec.interpretResponse(null, BUILD_REQUESTS_OUTPUT); expect(bids).to.be.empty; }); @@ -272,7 +334,7 @@ describe('Consumable BidAdapter', function () { it('should return a sync url if pixel syncs are enabled and some are returned from the server', function () { let syncOptions = {'pixelEnabled': true}; - let opts = spec.getUserSyncs(syncOptions, [RESPONSE]); + let opts = spec.getUserSyncs(syncOptions, [AD_SERVER_RESPONSE]); expect(opts.length).to.equal(1); }); From 259b6e0388187e720ec0f91836527e849fa90efd Mon Sep 17 00:00:00 2001 From: Hugo Duthil Date: Tue, 5 Nov 2019 14:19:07 +0100 Subject: [PATCH 372/436] CriteoId User Module (#4287) * Add CriteoId module * Update the return type of getId in Criteo Id module Changes: - Use of url parsing function from url lib - Update the return type of getId() - Update the jsdoc to reflect the real return types * Fix failing tests for Criteo user module * Add CriteoIdSystem submodule to .submodule.json. --- modules/.submodules.json | 3 +- modules/criteoIdSystem.js | 132 ++++++++++++++++++++++ test/spec/modules/criteoIdSystem_spec.js | 135 +++++++++++++++++++++++ 3 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 modules/criteoIdSystem.js create mode 100644 test/spec/modules/criteoIdSystem_spec.js diff --git a/modules/.submodules.json b/modules/.submodules.json index 09063deea40..130e7e8817e 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -4,7 +4,8 @@ "id5IdSystem", "criteortusIdSystem", "parrableIdSystem", - "liveIntentIdSystem" + "liveIntentIdSystem", + "criteoIdSystem" ], "adpod": [ "freeWheelAdserverVideo", diff --git a/modules/criteoIdSystem.js b/modules/criteoIdSystem.js new file mode 100644 index 00000000000..fe89de5d341 --- /dev/null +++ b/modules/criteoIdSystem.js @@ -0,0 +1,132 @@ +/** + * This module adds Criteo Real Time User Sync to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/criteoIdSystem + * @requires module:modules/userId + */ + +import * as utils from '../src/utils' +import * as ajax from '../src/ajax' +import * as urlLib from '../src/url' +import { getRefererInfo } from '../src/refererDetection' +import { submodule } from '../src/hook'; + +const bididStorageKey = 'cto_bidid'; +const bundleStorageKey = 'cto_bundle'; +const cookieWriteableKey = 'cto_test_cookie'; +const cookiesMaxAge = 13 * 30 * 24 * 60 * 60 * 1000; + +const pastDateString = new Date(0).toString(); +const expirationString = new Date(utils.timestamp() + cookiesMaxAge).toString(); + +function areCookiesWriteable() { + utils.setCookie(cookieWriteableKey, '1'); + const canWrite = utils.getCookie(cookieWriteableKey) === '1'; + utils.setCookie(cookieWriteableKey, '', pastDateString); + return canWrite; +} + +function extractProtocolHost (url, returnOnlyHost = false) { + const parsedUrl = urlLib.parse(url) + return returnOnlyHost + ? `${parsedUrl.hostname}` + : `${parsedUrl.protocol}://${parsedUrl.hostname}${parsedUrl.port ? ':' + parsedUrl.port : ''}/`; +} + +function getFromAllStorages(key) { + return utils.getCookie(key) || utils.getDataFromLocalStorage(key); +} + +function saveOnAllStorages(key, value) { + if (key && value) { + utils.setCookie(key, value, expirationString); + utils.setDataInLocalStorage(key, value); + } +} + +function deleteFromAllStorages(key) { + utils.setCookie(key, '', pastDateString); + utils.removeDataFromLocalStorage(key); +} + +function getCriteoDataFromAllStorages() { + return { + bundle: getFromAllStorages(bundleStorageKey), + bidId: getFromAllStorages(bididStorageKey), + } +} + +function buildCriteoUsersyncUrl(topUrl, domain, bundle, areCookiesWriteable, isPublishertagPresent) { + const url = 'https://gum.criteo.com/sid/json?origin=prebid' + + `${topUrl ? '&topUrl=' + encodeURIComponent(topUrl) : ''}` + + `${domain ? '&domain=' + encodeURIComponent(domain) : ''}` + + `${bundle ? '&bundle=' + encodeURIComponent(bundle) : ''}` + + `${areCookiesWriteable ? '&cw=1' : ''}` + + `${isPublishertagPresent ? '&pbt=1' : ''}` + + return url; +} + +function callCriteoUserSync(parsedCriteoData) { + const cw = areCookiesWriteable(); + const topUrl = extractProtocolHost(getRefererInfo().referer); + const domain = extractProtocolHost(document.location.href, true); + const isPublishertagPresent = typeof criteo_pubtag !== 'undefined'; // eslint-disable-line camelcase + + const url = buildCriteoUsersyncUrl( + topUrl, + domain, + parsedCriteoData.bundle, + cw, + isPublishertagPresent + ); + + ajax.ajaxBuilder()( + url, + response => { + const jsonResponse = JSON.parse(response); + if (jsonResponse.bidId) { + saveOnAllStorages(bididStorageKey, jsonResponse.bidId); + } else { + deleteFromAllStorages(bididStorageKey); + } + + if (jsonResponse.acwsUrl) { + const urlsToCall = typeof jsonResponse.acwsUrl === 'string' ? [jsonResponse.acwsUrl] : jsonResponse.acwsUrl; + urlsToCall.forEach(url => utils.triggerPixel(url)); + } else if (jsonResponse.bundle) { + saveOnAllStorages(bundleStorageKey, jsonResponse.bundle); + } + } + ); +} + +/** @type {Submodule} */ +export const criteoIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: 'criteo', + /** + * decode the stored id value for passing to bid requests + * @function + * @returns {{criteoId: string} | undefined} + */ + decode(bidId) { + return bidId; + }, + /** + * get the Criteo Id from local storages and initiate a new user sync + * @function + * @returns {{id: {criteoId: string} | undefined}}} + */ + getId() { + let localData = getCriteoDataFromAllStorages(); + callCriteoUserSync(localData); + + return { id: localData.bidId ? { criteoId: localData.bidId } : undefined } + } +}; + +submodule('userId', criteoIdSubmodule); diff --git a/test/spec/modules/criteoIdSystem_spec.js b/test/spec/modules/criteoIdSystem_spec.js new file mode 100644 index 00000000000..44decfd56b6 --- /dev/null +++ b/test/spec/modules/criteoIdSystem_spec.js @@ -0,0 +1,135 @@ +import { criteoIdSubmodule } from 'modules/criteoIdSystem'; +import * as utils from 'src/utils'; +import * as ajaxLib from 'src/ajax'; +import * as urlLib from 'src/url'; + +const pastDateString = new Date(0).toString() + +function mockResponse(responseText, fakeResponse = (url, callback) => callback(responseText)) { + return function() { + return fakeResponse; + } +} + +describe('CriteoId module', function () { + const cookiesMaxAge = 13 * 30 * 24 * 60 * 60 * 1000; + + const nowTimestamp = new Date().getTime(); + + let getCookieStub; + let setCookieStub; + let getLocalStorageStub; + let setLocalStorageStub; + let removeFromLocalStorageStub; + let timeStampStub; + let parseUrlStub; + let ajaxBuilderStub; + let triggerPixelStub; + + beforeEach(function (done) { + getCookieStub = sinon.stub(utils, 'getCookie'); + setCookieStub = sinon.stub(utils, 'setCookie'); + getLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); + setLocalStorageStub = sinon.stub(utils, 'setDataInLocalStorage'); + removeFromLocalStorageStub = sinon.stub(utils, 'removeDataFromLocalStorage'); + timeStampStub = sinon.stub(utils, 'timestamp').returns(nowTimestamp); + ajaxBuilderStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockResponse('{}')); + parseUrlStub = sinon.stub(urlLib, 'parse').returns({protocol: 'https', hostname: 'testdev.com'}) + triggerPixelStub = sinon.stub(utils, 'triggerPixel'); + done(); + }); + + afterEach(function () { + getCookieStub.restore(); + setCookieStub.restore(); + getLocalStorageStub.restore(); + setLocalStorageStub.restore(); + removeFromLocalStorageStub.restore(); + timeStampStub.restore(); + ajaxBuilderStub.restore(); + triggerPixelStub.restore(); + parseUrlStub.restore(); + }); + + const storageTestCases = [ + { cookie: 'bidId', localStorage: 'bidId2', expected: 'bidId' }, + { cookie: 'bidId', localStorage: undefined, expected: 'bidId' }, + { cookie: undefined, localStorage: 'bidId', expected: 'bidId' }, + { cookie: undefined, localStorage: undefined, expected: undefined }, + ] + + storageTestCases.forEach(testCase => it('getId() should return the bidId when it exists in local storages', function () { + getCookieStub.withArgs('cto_bidid').returns(testCase.cookie); + getLocalStorageStub.withArgs('cto_bidid').returns(testCase.localStorage); + + const id = criteoIdSubmodule.getId(); + expect(id).to.be.deep.equal({id: testCase.expected ? { criteoId: testCase.expected } : undefined}); + })) + + it('decode() should return the bidId when it exists in local storages', function () { + const id = criteoIdSubmodule.decode('testDecode'); + expect(id).to.equal('testDecode') + }); + + it('should call user sync url with the right params', function () { + getCookieStub.withArgs('cto_test_cookie').returns('1'); + getCookieStub.withArgs('cto_bundle').returns('bundle'); + window.criteo_pubtag = {} + + const emptyObj = '{}'; + let ajaxStub = sinon.stub().callsFake((url, callback) => callback(emptyObj)); + ajaxBuilderStub.callsFake(mockResponse(undefined, ajaxStub)) + + criteoIdSubmodule.getId(); + const expectedUrl = `https://gum.criteo.com/sid/json?origin=prebid&topUrl=https%3A%2F%2Ftestdev.com%2F&domain=testdev.com&bundle=bundle&cw=1&pbt=1`; + + expect(ajaxStub.calledWith(expectedUrl)).to.be.true; + + window.criteo_pubtag = undefined; + }); + + const responses = [ + { bundle: 'bundle', bidId: 'bidId', acwsUrl: 'acwsUrl' }, + { bundle: 'bundle', bidId: undefined, acwsUrl: 'acwsUrl' }, + { bundle: 'bundle', bidId: 'bidId', acwsUrl: undefined }, + { bundle: undefined, bidId: 'bidId', acwsUrl: 'acwsUrl' }, + { bundle: 'bundle', bidId: undefined, acwsUrl: undefined }, + { bundle: undefined, bidId: 'bidId', acwsUrl: undefined }, + { bundle: undefined, bidId: undefined, acwsUrl: 'acwsUrl' }, + { bundle: undefined, bidId: undefined, acwsUrl: ['acwsUrl', 'acwsUrl2'] }, + { bundle: undefined, bidId: undefined, acwsUrl: undefined }, + ] + + responses.forEach(response => describe('test user sync response behavior', function () { + const expirationTs = new Date(nowTimestamp + cookiesMaxAge).toString(); + + beforeEach(function (done) { + const fakeResponse = (url, callback) => { + callback(JSON.stringify(response)); + setTimeout(done, 0); + } + ajaxBuilderStub.callsFake(mockResponse(undefined, fakeResponse)); + criteoIdSubmodule.getId(); + }) + + it('should save bidId if it exists', function () { + if (response.acwsUrl) { + expect(triggerPixelStub.called).to.be.true; + expect(setCookieStub.calledWith('cto_bundle')).to.be.false; + expect(setLocalStorageStub.calledWith('cto_bundle')).to.be.false; + } else if (response.bundle) { + expect(setCookieStub.calledWith('cto_bundle', response.bundle, expirationTs)).to.be.true; + expect(setLocalStorageStub.calledWith('cto_bundle', response.bundle)).to.be.true; + expect(triggerPixelStub.called).to.be.false; + } + + if (response.bidId) { + expect(setCookieStub.calledWith('cto_bidid', response.bidId, expirationTs)).to.be.true; + expect(setLocalStorageStub.calledWith('cto_bidid', response.bidId)).to.be.true; + } else { + expect(setCookieStub.calledWith('cto_bidid', '', pastDateString)).to.be.true; + expect(removeFromLocalStorageStub.calledWith('cto_bidid')).to.be.true; + } + }); + })); +}); From 09a09c486a4760a010a1ca2b4db7291c2649b83f Mon Sep 17 00:00:00 2001 From: kpis-msa <50609476+kpis-msa@users.noreply.github.com> Date: Tue, 5 Nov 2019 22:33:26 +0900 Subject: [PATCH 373/436] 2019/10/18 Create Mobsmart bidder adapter (#4339) --- modules/mobsmartBidAdapter.js | 94 ++++++++ modules/mobsmartBidAdapter.md | 50 +++++ test/spec/modules/mobsmartBidAdapter_spec.js | 214 +++++++++++++++++++ 3 files changed, 358 insertions(+) create mode 100644 modules/mobsmartBidAdapter.js create mode 100644 modules/mobsmartBidAdapter.md create mode 100644 test/spec/modules/mobsmartBidAdapter_spec.js diff --git a/modules/mobsmartBidAdapter.js b/modules/mobsmartBidAdapter.js new file mode 100644 index 00000000000..ba02aef38ef --- /dev/null +++ b/modules/mobsmartBidAdapter.js @@ -0,0 +1,94 @@ +import { registerBidder } from '../src/adapters/bidderFactory'; +import { config } from '../src/config'; + +const BIDDER_CODE = 'mobsmart'; +const ENDPOINT = 'https://prebid.mobsmart.net/prebid/endpoint'; + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function(bid) { + if (bid.bidder !== BIDDER_CODE) { + return false; + } + + return true; + }, + buildRequests: function(validBidRequests, bidderRequest) { + const timeout = config.getConfig('bidderTimeout'); + const referrer = encodeURIComponent(bidderRequest.refererInfo.referer); + + return validBidRequests.map(bidRequest => { + const adUnit = { + code: bidRequest.adUnitCode, + bids: { + bidder: bidRequest.bidder, + params: bidRequest.params + }, + mediaTypes: bidRequest.mediaTypes + }; + + if (bidRequest.hasOwnProperty('sizes') && bidRequest.sizes.length > 0) { + adUnit.sizes = bidRequest.sizes; + } + + const request = { + auctionId: bidRequest.auctionId, + requestId: bidRequest.bidId, + bidRequestsCount: bidRequest.bidRequestsCount, + bidderRequestId: bidRequest.bidderRequestId, + transactionId: bidRequest.transactionId, + referrer: referrer, + timeout: timeout, + adUnit: adUnit + }; + + if (bidRequest.userId && bidRequest.userId.pubcid) { + request.userId = {pubcid: bidRequest.userId.pubcid}; + } + + return { + method: 'POST', + url: ENDPOINT, + data: JSON.stringify(request) + } + }); + }, + interpretResponse: function(serverResponse) { + const bidResponses = []; + + if (serverResponse.body) { + const response = serverResponse.body; + const bidResponse = { + 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.ad, + }; + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + let syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: 'https://tags.mobsmart.net/tags/iframe' + }); + } else if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: 'https://tags.mobsmart.net/tags/image' + }); + } + + return syncs; + } +} +registerBidder(spec); diff --git a/modules/mobsmartBidAdapter.md b/modules/mobsmartBidAdapter.md new file mode 100644 index 00000000000..1240d6db494 --- /dev/null +++ b/modules/mobsmartBidAdapter.md @@ -0,0 +1,50 @@ +# Overview + +``` +Module Name: Mobsmart Bidder Adapter +Module Type: Bidder Adapter +Maintainer: adx@kpis.jp +``` + +# Description + +Module that connects to Mobsmart demand sources to fetch bids. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "mobsmart", + params: { + floorPrice: 100, + currency: 'JPY' + } + } + ] + },{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[320, 50]], // a mobile size + } + }, + bids: [ + { + bidder: "mobsmart", + params: { + floorPrice: 90, + currency: 'JPY' + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/mobsmartBidAdapter_spec.js b/test/spec/modules/mobsmartBidAdapter_spec.js new file mode 100644 index 00000000000..7c1128276ab --- /dev/null +++ b/test/spec/modules/mobsmartBidAdapter_spec.js @@ -0,0 +1,214 @@ +import { expect } from 'chai'; +import { spec } from 'modules/mobsmartBidAdapter'; + +describe('mobsmartBidAdapter', function () { + describe('isBidRequestValid', function () { + let bid; + beforeEach(function() { + bid = { + bidder: 'mobsmart', + params: { + floorPrice: 100, + currency: 'JPY' + }, + mediaTypes: { + banner: { + size: [[300, 250]] + } + } + }; + }); + + it('should return true when valid bid request is set', function() { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when bidder is not set to "mobsmart"', function() { + bid.bidder = 'bidder'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when params are not set', function() { + delete bid.params.floorPrice; + delete bid.params.currency; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + + describe('buildRequests', function () { + let bidRequests; + beforeEach(function() { + bidRequests = [ + { + bidder: 'mobsmart', + adUnitCode: 'mobsmart-ad-code', + auctionId: 'auctionid-123', + bidId: 'bidid123', + bidRequestsCount: 1, + bidderRequestId: 'bidderrequestid123', + transactionId: 'transaction-id-123', + sizes: [[300, 250]], + requestId: 'requestid123', + params: { + floorPrice: 100, + currency: 'JPY' + }, + mediaTypes: { + banner: { + size: [[300, 250]] + } + }, + userId: { + pubcid: 'pubc-id-123' + } + }, { + bidder: 'mobsmart', + adUnitCode: 'mobsmart-ad-code2', + auctionId: 'auctionid-456', + bidId: 'bidid456', + bidRequestsCount: 1, + bidderRequestId: 'bidderrequestid456', + transactionId: 'transaction-id-456', + sizes: [[320, 50]], + requestId: 'requestid456', + params: { + floorPrice: 100, + currency: 'JPY' + }, + mediaTypes: { + banner: { + size: [[320, 50]] + } + }, + userId: { + pubcid: 'pubc-id-456' + } + } + ]; + }); + + let bidderRequest = { + refererInfo: { + referer: 'https://example.com' + } + }; + + it('should not contain a sizes when sizes is not set', function() { + delete bidRequests[0].sizes; + delete bidRequests[1].sizes; + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].data.sizes).to.be.an('undefined'); + expect(requests[1].data.sizes).to.be.an('undefined'); + }); + + it('should not contain a userId when userId is not set', function() { + delete bidRequests[0].userId; + delete bidRequests[1].userId; + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].data.userId).to.be.an('undefined'); + expect(requests[1].data.userId).to.be.an('undefined'); + }); + + it('should have a post method', function() { + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].method).to.equal('POST'); + expect(requests[1].method).to.equal('POST'); + }); + + it('should contain a request id equals to the bid id', function() { + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(JSON.parse(requests[0].data).requestId).to.equal(bidRequests[0].bidId); + expect(JSON.parse(requests[1].data).requestId).to.equal(bidRequests[1].bidId); + }); + + it('should have an url that match the default endpoint', function() { + let requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].url).to.equal('https://prebid.mobsmart.net/prebid/endpoint'); + expect(requests[1].url).to.equal('https://prebid.mobsmart.net/prebid/endpoint'); + }); + }); + + describe('interpretResponse', function () { + let serverResponse; + beforeEach(function() { + serverResponse = { + body: { + 'requestId': 'request-id', + 'cpm': 100, + 'width': 300, + 'height': 250, + 'ad': '
ad
', + 'ttl': 300, + 'creativeId': 'creative-id', + 'netRevenue': true, + 'currency': 'JPY' + } + }; + }); + + it('should return a valid response', () => { + var responses = spec.interpretResponse(serverResponse); + expect(responses).to.be.an('array').that.is.not.empty; + + let response = responses[0]; + expect(response).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', + 'netRevenue', 'currency'); + expect(response.requestId).to.equal('request-id'); + expect(response.cpm).to.equal(100); + expect(response.width).to.equal(300); + expect(response.height).to.equal(250); + expect(response.ad).to.equal('
ad
'); + expect(response.ttl).to.equal(300); + expect(response.creativeId).to.equal('creative-id'); + expect(response.netRevenue).to.be.true; + expect(response.currency).to.equal('JPY'); + }); + + it('should return an empty array when serverResponse is empty', () => { + serverResponse = {}; + var responses = spec.interpretResponse(serverResponse); + expect(responses).to.deep.equal([]); + }); + }); + + describe('getUserSyncs', function () { + it('should return nothing when sync is disabled', function () { + const syncOptions = { + 'iframeEnabled': false, + 'pixelEnabled': false + } + let syncs = spec.getUserSyncs(syncOptions); + expect(syncs).to.deep.equal([]); + }); + + it('should register iframe sync when iframe is enabled', function () { + const syncOptions = { + 'iframeEnabled': true, + 'pixelEnabled': false + } + let syncs = spec.getUserSyncs(syncOptions); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.equal('https://tags.mobsmart.net/tags/iframe'); + }); + + it('should register image sync when image is enabled', function () { + const syncOptions = { + 'iframeEnabled': false, + 'pixelEnabled': true + } + let syncs = spec.getUserSyncs(syncOptions); + expect(syncs[0].type).to.equal('image'); + expect(syncs[0].url).to.equal('https://tags.mobsmart.net/tags/image'); + }); + + it('should register iframe sync when iframe is enabled', function () { + const syncOptions = { + 'iframeEnabled': true, + 'pixelEnabled': true + } + let syncs = spec.getUserSyncs(syncOptions); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.equal('https://tags.mobsmart.net/tags/iframe'); + }); + }); +}); From e30af2624511a1d3fbd9056e721e5170031ffad2 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 5 Nov 2019 13:49:33 -0500 Subject: [PATCH 374/436] Adpod deal support (#4389) * Adpod deal support * Replacing filterBids with minTier * fix potential issue --- modules/adpod.js | 47 ++++++++-- modules/appnexusBidAdapter.js | 2 + test/spec/modules/adpod_spec.js | 77 ++++++++++++++++ .../modules/freeWheelAdserverVideo_spec.js | 90 +++++++++++++++++++ 4 files changed, 210 insertions(+), 6 deletions(-) diff --git a/modules/adpod.js b/modules/adpod.js index 875809b8df5..923912d7282 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -112,6 +112,19 @@ function createDispatcher(timeoutDuration) { }; } +function getPricePartForAdpodKey(bid) { + let pricePart + let prioritizeDeals = config.getConfig('adpod.prioritizeDeals'); + if (prioritizeDeals && utils.deepAccess(bid, 'video.dealTier')) { + const adpodDealPrefix = config.getConfig(`adpod.dealTier.${bid.bidderCode}.prefix`); + pricePart = (adpodDealPrefix) ? adpodDealPrefix + utils.deepAccess(bid, 'video.dealTier') : utils.deepAccess(bid, 'video.dealTier'); + } else { + const granularity = getPriceGranularity(bid.mediaType); + pricePart = getPriceByGranularity(granularity)(bid); + } + return pricePart +} + /** * This function reads certain fields from the bid to generate a specific key used for caching the bid in Prebid Cache * @param {Object} bid bid object to update @@ -120,16 +133,14 @@ function createDispatcher(timeoutDuration) { function attachPriceIndustryDurationKeyToBid(bid, brandCategoryExclusion) { let initialCacheKey = bidCacheRegistry.getInitialCacheKey(bid); let duration = utils.deepAccess(bid, 'video.durationBucket'); - const granularity = getPriceGranularity(bid.mediaType); - let cpmFixed = getPriceByGranularity(granularity)(bid); - + const pricePart = getPricePartForAdpodKey(bid); let pcd; if (brandCategoryExclusion) { let category = utils.deepAccess(bid, 'meta.adServerCatId'); - pcd = `${cpmFixed}_${category}_${duration}s`; + pcd = `${pricePart}_${category}_${duration}s`; } else { - pcd = `${cpmFixed}_${duration}s`; + pcd = `${pricePart}_${duration}s`; } if (!bid.adserverTargeting) { @@ -457,7 +468,31 @@ export function getTargeting({codes, callback} = {}) { let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; - bids.sort(sortByPricePerSecond); + + let prioritizeDeals = config.getConfig('adpod.prioritizeDeals'); + if (prioritizeDeals) { + let [otherBids, highPriorityDealBids] = bids.reduce((partitions, bid) => { + let bidDealTier = utils.deepAccess(bid, 'video.dealTier'); + let minDealTier = config.getConfig(`adpod.dealTier.${bid.bidderCode}.minDealTier`); + if (minDealTier && bidDealTier) { + if (bidDealTier >= minDealTier) { + partitions[1].push(bid) + } else { + partitions[0].push(bid) + } + } else if (bidDealTier) { + partitions[1].push(bid) + } else { + partitions[0].push(bid); + } + return partitions; + }, [[], []]); + highPriorityDealBids.sort(sortByPricePerSecond); + otherBids.sort(sortByPricePerSecond); + bids = highPriorityDealBids.concat(otherBids); + } else { + bids.sort(sortByPricePerSecond); + } let targeting = {}; if (deferCachingEnabled === false) { diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 95f5c162657..cb48f4cbd84 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -498,9 +498,11 @@ function newBid(serverBid, rtbBid, bidderRequest) { case ADPOD: const iabSubCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); bid.meta = Object.assign({}, bid.meta, { iabSubCatId }); + const dealTier = rtbBid.rtb.dealPriority; bid.video = { context: ADPOD, durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), + dealTier }; bid.vastUrl = rtbBid.rtb.video.asset_url; break; diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js index 8b7701c5631..f8c5387b6ce 100644 --- a/test/spec/modules/adpod_spec.js +++ b/test/spec/modules/adpod_spec.js @@ -766,6 +766,83 @@ describe('adpod.js', function () { expect(storeStub.called).to.equal(false); expect(auctionBids.length).to.equal(1); }); + + it('should set deal tier in place of cpm when prioritzeDeals is true', function() { + config.setConfig({ + adpod: { + deferCaching: true, + brandCategoryExclusion: true, + prioritizeDeals: true, + dealTier: { + 'appnexus': { + 'prefix': 'tier', + 'minDealTier': 5 + } + } + } + }); + + let bidResponse1 = { + adId: 'adId01277', + auctionId: 'no_defer_123', + mediaType: 'video', + bidderCode: 'appnexus', + cpm: 5, + pbMg: '5.00', + adserverTargeting: { + hb_pb: '5.00' + }, + meta: { + adServerCatId: 'test' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15, + dealTier: 7 + } + }; + + let bidResponse2 = { + adId: 'adId46547', + auctionId: 'no_defer_123', + mediaType: 'video', + bidderCode: 'appnexus', + cpm: 12, + pbMg: '12.00', + adserverTargeting: { + hb_pb: '12.00' + }, + meta: { + adServerCatId: 'value' + }, + video: { + context: ADPOD, + durationSeconds: 15, + durationBucket: 15 + } + }; + + let bidderRequest = { + adUnitCode: 'adpod_1', + auctionId: 'no_defer_123', + mediaTypes: { + video: { + context: ADPOD, + playerSize: [300, 300], + adPodDurationSec: 300, + durationRangeSec: [15, 30, 45], + requireExactDuration: false + } + }, + }; + + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); + callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, bidderRequest); + + expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('tier7_test_15s'); + expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('12.00_value_15s'); + }) }); describe('checkAdUnitSetupHook', function () { diff --git a/test/spec/modules/freeWheelAdserverVideo_spec.js b/test/spec/modules/freeWheelAdserverVideo_spec.js index f958a2733db..c2afaf8d69f 100644 --- a/test/spec/modules/freeWheelAdserverVideo_spec.js +++ b/test/spec/modules/freeWheelAdserverVideo_spec.js @@ -197,6 +197,96 @@ describe('freeWheel adserver module', function() { expect(targeting['preroll_1'].length).to.equal(3); expect(targeting['midroll_1'].length).to.equal(3); }); + + it('should prioritize bids with deal', function() { + config.setConfig({ + adpod: { + deferCaching: true, + prioritizeDeals: true + } + }); + + let tier6Bid = createBid(10, 'preroll_1', 15, 'tier6_395_15s', '123', '395'); + tier6Bid['video']['dealTier'] = 'tier6' + + let tier7Bid = createBid(11, 'preroll_1', 45, 'tier7_395_15s', '123', '395'); + tier7Bid['video']['dealTier'] = 'tier7' + + let bidsReceived = [ + tier6Bid, + tier7Bid, + createBid(15, 'preroll_1', 90, '15.00_395_90s', '123', '395'), + ] + amStub.returns(bidsReceived); + let targeting; + adpodUtils.getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify({'responses': bidsReceived.slice(1)}) + ); + + expect(targeting['preroll_1'].length).to.equal(3); + expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': 'tier6_395_15s'}); + expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': 'tier7_395_15s'}); + expect(targeting['preroll_1']).to.deep.include({'hb_cache_id': '123'}); + }); + + it('should apply minDealTier to bids if configured', function() { + config.setConfig({ + adpod: { + deferCaching: true, + prioritizeDeals: true, + dealTier: { + 'appnexus': { + prefix: 'tier', + minDealTier: 5 + } + } + } + }); + + let tier2Bid = createBid(10, 'preroll_1', 15, 'tier2_395_15s', '123', '395'); + tier2Bid['video']['dealTier'] = 2 + tier2Bid['adserverTargeting']['hb_pb'] = '10.00' + + let tier7Bid = createBid(11, 'preroll_1', 45, 'tier7_395_15s', '123', '395'); + tier7Bid['video']['dealTier'] = 7 + tier7Bid['adserverTargeting']['hb_pb'] = '11.00' + + let bid = createBid(15, 'preroll_1', 15, '15.00_395_90s', '123', '395'); + bid['adserverTargeting']['hb_pb'] = '15.00' + + let bidsReceived = [ + tier2Bid, + tier7Bid, + bid + ] + amStub.returns(bidsReceived); + let targeting; + adpodUtils.getTargeting({ + callback: function(errorMsg, targetingResult) { + targeting = targetingResult; + } + }); + + requests[0].respond( + 200, + { 'Content-Type': 'text/plain' }, + JSON.stringify({'responses': [tier7Bid, bid]}) + ); + + expect(targeting['preroll_1'].length).to.equal(3); + expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': 'tier7_395_15s'}); + expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': '15.00_395_90s'}); + expect(targeting['preroll_1']).to.not.include({'hb_pb_cat_dur': 'tier2_395_15s'}); + expect(targeting['preroll_1']).to.deep.include({'hb_cache_id': '123'}); + }) }); function getBidsReceived() { From 0bfd7686281b1f22cf7abf88ff7220db0b2d6577 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal <7393273+jaiminpanchal27@users.noreply.github.com> Date: Tue, 5 Nov 2019 14:55:19 -0500 Subject: [PATCH 375/436] remove querystringify package (#4422) --- package-lock.json | 3504 ++++++++++++++------ package.json | 1 - test/spec/modules/polluxBidAdapter_spec.js | 4 +- 3 files changed, 2486 insertions(+), 1023 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7256dd8e2d..ffde0ad63ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.35.0-pre", + "version": "2.39.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.2.tgz", - "integrity": "sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.0.tgz", + "integrity": "sha512-Bb1NjZCaiwTQC/ARL+MwDpgocdnwWDCaugvkGt6cxfBzQa8Whv1JybBoUEiBDKl8Ni3H3c7Fykwk7QChUsHRlg==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helpers": "^7.6.2", - "@babel/parser": "^7.6.2", - "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.2", - "@babel/types": "^7.6.0", + "@babel/generator": "^7.7.0", + "@babel/helpers": "^7.7.0", + "@babel/parser": "^7.7.0", + "@babel/template": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -36,136 +36,146 @@ } }, "@babel/generator": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", - "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.0.tgz", + "integrity": "sha512-1wdJ6UxHyL1XoJQ119JmvuRX27LRih7iYStMPZOWAjQqeAabFg3dYXKMpgihma+to+0ADsTVVt6oRyUxWZw6Mw==", "dev": true, "requires": { - "@babel/types": "^7.6.0", + "@babel/types": "^7.7.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" } }, "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz", + "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.7.0" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz", + "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-explode-assignable-expression": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helper-call-delegate": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz", + "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.0.tgz", + "integrity": "sha512-ZhagAAVGD3L6MPM9/zZi7RRteonfBFLVUz3kjsnYsMAtr9hOJCKI9BAKIMpqn3NyWicPieoX779UL+7/3BEAOA==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" } }, "@babel/helper-define-map": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", - "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz", + "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.5.5", + "@babel/helper-function-name": "^7.7.0", + "@babel/types": "^7.7.0", "lodash": "^4.17.13" } }, "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz", + "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==", "dev": true, "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", + "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-get-function-arity": "^7.7.0", + "@babel/template": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", + "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.7.0" } }, "@babel/helper-hoist-variables": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz", + "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==", "dev": true, "requires": { - "@babel/types": "^7.4.4" + "@babel/types": "^7.7.0" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", - "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz", + "integrity": "sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==", "dev": true, "requires": { - "@babel/types": "^7.5.5" + "@babel/types": "^7.7.0" } }, "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz", + "integrity": "sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.7.0" } }, "@babel/helper-module-transforms": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", - "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz", + "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.5.5", + "@babel/helper-module-imports": "^7.7.0", + "@babel/helper-simple-access": "^7.7.0", + "@babel/helper-split-export-declaration": "^7.7.0", + "@babel/template": "^7.7.0", + "@babel/types": "^7.7.0", "lodash": "^4.17.13" } }, "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz", + "integrity": "sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.7.0" } }, "@babel/helper-plugin-utils": { @@ -184,70 +194,70 @@ } }, "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz", + "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-annotate-as-pure": "^7.7.0", + "@babel/helper-wrap-function": "^7.7.0", + "@babel/template": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helper-replace-supers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", - "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz", + "integrity": "sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.5.5", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/helper-member-expression-to-functions": "^7.7.0", + "@babel/helper-optimise-call-expression": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz", + "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==", "dev": true, "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/template": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", + "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", "dev": true, "requires": { - "@babel/types": "^7.4.4" + "@babel/types": "^7.7.0" } }, "@babel/helper-wrap-function": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz", + "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" + "@babel/helper-function-name": "^7.7.0", + "@babel/template": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/helpers": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.2.tgz", - "integrity": "sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz", + "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==", "dev": true, "requires": { - "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.2", - "@babel/types": "^7.6.0" + "@babel/template": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/highlight": { @@ -262,26 +272,26 @@ } }, "@babel/parser": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", - "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.0.tgz", + "integrity": "sha512-GqL+Z0d7B7ADlQBMXlJgvXEbtt5qlqd1YQ5fr12hTSfh7O/vgrEIvJxU2e7aSVrEUn75zTZ6Nd0s8tthrlZnrQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz", + "integrity": "sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/helper-remap-async-to-generator": "^7.7.0", "@babel/plugin-syntax-async-generators": "^7.2.0" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", - "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz", + "integrity": "sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -319,14 +329,13 @@ } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz", - "integrity": "sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz", + "integrity": "sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" + "@babel/helper-create-regexp-features-plugin": "^7.7.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-async-generators": { @@ -374,6 +383,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz", + "integrity": "sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", @@ -384,14 +402,14 @@ } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", - "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz", + "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-module-imports": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" + "@babel/helper-remap-async-to-generator": "^7.7.0" } }, "@babel/plugin-transform-block-scoped-functions": { @@ -404,9 +422,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz", - "integrity": "sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", + "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -414,18 +432,18 @@ } }, "@babel/plugin-transform-classes": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", - "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz", + "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.5.5", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-annotate-as-pure": "^7.7.0", + "@babel/helper-define-map": "^7.7.0", + "@babel/helper-function-name": "^7.7.0", + "@babel/helper-optimise-call-expression": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", - "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/helper-replace-supers": "^7.7.0", + "@babel/helper-split-export-declaration": "^7.7.0", "globals": "^11.1.0" } }, @@ -448,14 +466,13 @@ } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz", - "integrity": "sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz", + "integrity": "sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" + "@babel/helper-create-regexp-features-plugin": "^7.7.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-duplicate-keys": { @@ -487,12 +504,12 @@ } }, "@babel/plugin-transform-function-name": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz", + "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", + "@babel/helper-function-name": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0" } }, @@ -526,45 +543,45 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz", - "integrity": "sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz", + "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-module-transforms": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-simple-access": "^7.7.0", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", - "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz", + "integrity": "sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-hoist-variables": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz", + "integrity": "sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-module-transforms": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz", - "integrity": "sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz", + "integrity": "sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg==", "dev": true, "requires": { - "regexpu-core": "^4.6.0" + "@babel/helper-create-regexp-features-plugin": "^7.7.0" } }, "@babel/plugin-transform-new-target": { @@ -607,9 +624,9 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", - "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz", + "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==", "dev": true, "requires": { "regenerator-transform": "^0.14.0" @@ -672,67 +689,67 @@ } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz", - "integrity": "sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz", + "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" + "@babel/helper-create-regexp-features-plugin": "^7.7.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/preset-env": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.2.tgz", - "integrity": "sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.1.tgz", + "integrity": "sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-module-imports": "^7.7.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", + "@babel/plugin-proposal-async-generator-functions": "^7.7.0", + "@babel/plugin-proposal-dynamic-import": "^7.7.0", "@babel/plugin-proposal-json-strings": "^7.2.0", "@babel/plugin-proposal-object-rest-spread": "^7.6.2", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.6.2", + "@babel/plugin-proposal-unicode-property-regex": "^7.7.0", "@babel/plugin-syntax-async-generators": "^7.2.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-syntax-top-level-await": "^7.7.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-async-to-generator": "^7.7.0", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.6.2", - "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-block-scoping": "^7.6.3", + "@babel/plugin-transform-classes": "^7.7.0", "@babel/plugin-transform-computed-properties": "^7.2.0", "@babel/plugin-transform-destructuring": "^7.6.0", - "@babel/plugin-transform-dotall-regex": "^7.6.2", + "@babel/plugin-transform-dotall-regex": "^7.7.0", "@babel/plugin-transform-duplicate-keys": "^7.5.0", "@babel/plugin-transform-exponentiation-operator": "^7.2.0", "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.7.0", "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-member-expression-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.6.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.2", + "@babel/plugin-transform-modules-commonjs": "^7.7.0", + "@babel/plugin-transform-modules-systemjs": "^7.7.0", + "@babel/plugin-transform-modules-umd": "^7.7.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.0", "@babel/plugin-transform-new-target": "^7.4.4", "@babel/plugin-transform-object-super": "^7.5.5", "@babel/plugin-transform-parameters": "^7.4.4", "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-regenerator": "^7.7.0", "@babel/plugin-transform-reserved-words": "^7.2.0", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.6.2", "@babel/plugin-transform-sticky-regex": "^7.2.0", "@babel/plugin-transform-template-literals": "^7.4.4", "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.6.2", - "@babel/types": "^7.6.0", + "@babel/plugin-transform-unicode-regex": "^7.7.0", + "@babel/types": "^7.7.1", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -741,37 +758,37 @@ } }, "@babel/template": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", - "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", + "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0" + "@babel/parser": "^7.7.0", + "@babel/types": "^7.7.0" } }, "@babel/traverse": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", - "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.0.tgz", + "integrity": "sha512-ea/3wRZc//e/uwCpuBX2itrhI0U9l7+FsrKWyKGNyvWbuMcCG7ATKY2VI4wlg2b2TA39HHwIxnvmXvtiKsyn7w==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.2", - "@babel/types": "^7.6.0", + "@babel/generator": "^7.7.0", + "@babel/helper-function-name": "^7.7.0", + "@babel/helper-split-export-declaration": "^7.7.0", + "@babel/parser": "^7.7.0", + "@babel/types": "^7.7.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" } }, "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.1.tgz", + "integrity": "sha512-kN/XdANDab9x1z5gcjDc9ePpxexkt+1EQ2MQUiM4XnMvQfvp87/+6kY4Ko2maLXH+tei/DgJ/ybFITeqqRwDiA==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -779,6 +796,16 @@ "to-fast-properties": "^2.0.0" } }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, "@gulp-sourcemaps/identity-map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", @@ -830,6 +857,241 @@ } } }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", @@ -871,6 +1133,93 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.0.tgz", + "integrity": "sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz", + "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -881,6 +1230,12 @@ "through": ">=2.2.7 <3" } }, + "abab": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz", + "integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg==", + "dev": true + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -920,6 +1275,24 @@ } } }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + } + } + }, "acorn-jsx": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", @@ -1005,10 +1378,13 @@ "dev": true }, "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } }, "ansi-escapes": { "version": "3.2.0", @@ -1206,6 +1582,12 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1377,6 +1759,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -1729,16 +2117,39 @@ "babel-template": "^6.24.1" } }, - "babel-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", - "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", "dev": true, "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "babel-loader": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" } }, "babel-messages": { @@ -1768,6 +2179,27 @@ "object.assign": "^4.1.0" } }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, "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", @@ -2398,6 +2830,16 @@ "babel-plugin-transform-flow-strip-types": "^6.22.0" } }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", @@ -2753,9 +3195,9 @@ "dev": true }, "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", "dev": true }, "bn.js": { @@ -2905,6 +3347,12 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", @@ -3000,14 +3448,14 @@ } }, "browserslist": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", - "integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz", + "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000989", - "electron-to-chromium": "^1.3.247", - "node-releases": "^1.1.29" + "caniuse-lite": "^1.0.30001004", + "electron-to-chromium": "^1.3.295", + "node-releases": "^1.1.38" } }, "browserstack": { @@ -3031,6 +3479,15 @@ "temp-fs": "^0.9.9" } }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, "buffer": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", @@ -3189,6 +3646,14 @@ "dev": true, "requires": { "callsites": "^0.2.0" + }, + "dependencies": { + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + } } }, "callsite": { @@ -3198,9 +3663,9 @@ "dev": true }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { @@ -3228,11 +3693,20 @@ } }, "caniuse-lite": { - "version": "1.0.30000997", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000997.tgz", - "integrity": "sha512-BQLFPIdj2ntgBNWp9Q64LGUIEmvhKkzzHhUHR3CD5A9Lb7ZKF20/+sgadhFap69lk5XmK1fTUleDclaRFvgVUA==", + "version": "1.0.30001008", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz", + "integrity": "sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw==", "dev": true }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -3342,6 +3816,12 @@ "upath": "^1.1.1" } }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3397,29 +3877,29 @@ "dev": true }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } } } @@ -3553,9 +4033,9 @@ "dev": true }, "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "commondir": { @@ -3676,13 +4156,10 @@ "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" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true }, "constants-browserify": { "version": "1.0.0", @@ -3755,17 +4232,17 @@ } }, "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" }, "core-js-compat": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.2.1.tgz", - "integrity": "sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.3.6.tgz", + "integrity": "sha512-YnwZG/+0/f7Pf6Lr3jxtVAFjtGBW9lsLYcqrxhYJai1GfvrP8DEyEpnNzj/FRQfIkOOfk1j5tTBvPBLWVVJm4A==", "dev": true, "requires": { - "browserslist": "^4.6.6", + "browserslist": "^4.7.2", "semver": "^6.3.0" }, "dependencies": { @@ -3784,9 +4261,9 @@ "dev": true }, "coveralls": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.6.tgz", - "integrity": "sha512-Pgh4v3gCI4T/9VijVrm8Ym5v0OgjvGLKj3zTUwkvsCiwqae/p6VLzpsFNjQS2i6ewV7ef+DjFJ5TSKxYt/mCrA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.7.tgz", + "integrity": "sha512-mUuH2MFOYB2oBaA4D4Ykqi9LaEYpMMlsiOMJOrv358yAjP6enPIk55fod2fNJ8AvwoYXStWQls37rA+s5e7boA==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -3925,6 +4402,21 @@ "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", "dev": true }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -3959,18 +4451,36 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, "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": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", @@ -4239,6 +4749,12 @@ "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", "dev": true }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -4350,6 +4866,12 @@ "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 + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", @@ -4380,32 +4902,6 @@ } } }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -4421,12 +4917,6 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -4436,15 +4926,6 @@ "number-is-nan": "^1.0.0" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -4475,32 +4956,6 @@ "path-exists": "^3.0.0" } }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -4574,6 +5029,56 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "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" + }, + "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 + }, + "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" + } + } + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", @@ -4642,6 +5147,15 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "dset": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/dset/-/dset-2.0.1.tgz", @@ -4719,9 +5233,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.266", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.266.tgz", - "integrity": "sha512-UTuTZ4v8T0gLPHI7U75PXLQePWI65MTS3mckRrnLCkNljHvsutbYs+hn2Ua/RFul3Jt/L3Ht2rLP+dU/AlBfrQ==", + "version": "1.3.303", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.303.tgz", + "integrity": "sha512-xDFPmMjJ0gQBsVwspB0bjcbFn3MVcvU0sxXYmh1UMbZ6rDogQVM3vSyOvTO4rym1KlnJIU6nqzK3qs0yKudmjw==", "dev": true }, "elliptic": { @@ -4794,6 +5308,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } } } }, @@ -4836,6 +5361,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } } } }, @@ -4898,9 +5434,9 @@ } }, "es-abstract": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz", - "integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", "dev": true, "requires": { "es-to-primitive": "^1.2.0", @@ -4911,8 +5447,8 @@ "is-regex": "^1.0.4", "object-inspect": "^1.6.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.0.0", - "string.prototype.trimright": "^2.0.0" + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { @@ -4927,14 +5463,14 @@ } }, "es5-ext": { - "version": "0.10.51", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz", - "integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==", + "version": "0.10.52", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.52.tgz", + "integrity": "sha512-bWCbE9fbpYQY4CU6hJbJ1vSz70EClMlDgJ7BmwI+zEJhxrwjesZRPglGJlsZhu0334U3hI+gaspwksH9IGD6ag==", "dev": true, "requires": { "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" + "es6-symbol": "~3.1.2", + "next-tick": "~1.0.0" } }, "es5-shim": { @@ -5009,13 +5545,13 @@ } }, "es6-symbol": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz", - "integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { "d": "^1.0.1", - "es5-ext": "^0.10.51" + "ext": "^1.1.2" } }, "es6-weak-map": { @@ -5043,39 +5579,30 @@ "dev": true }, "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", "dev": true, "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", + "esprima": "^3.1.3", + "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", - "source-map": "~0.2.0" + "source-map": "~0.6.1" }, "dependencies": { "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true }, "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true } } }, @@ -5590,6 +6117,12 @@ "safe-buffer": "^5.1.1" } }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -5616,6 +6149,12 @@ } } }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", @@ -5733,6 +6272,20 @@ "homedir-polyfill": "^1.0.1" } }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -5854,6 +6407,23 @@ } } }, + "ext": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.1.2.tgz", + "integrity": "sha512-/KLjJdTNyDepCihrk4HQt57nAE1IRCEo5jUt+WgWGCr1oARhibDvmI2DMcSNWood1T9AUWwq+jaV1wvRqaXfnA==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6008,9 +6578,18 @@ "websocket-driver": ">=0.5.1" } }, - "fibers": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "fibers": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-3.1.1.tgz", "integrity": "sha512-dl3Ukt08rHVQfY8xGD0ODwyjwrRALtaghuqGH2jByYX1wpY+nAnRQjJ6Dbqq0DnVgNVQ9yibObzbF4IlPyiwPw==", "dev": true, "requires": { @@ -6164,23 +6743,6 @@ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true - } - } - }, "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", @@ -6353,6 +6915,12 @@ "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 } } }, @@ -6411,7 +6979,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6432,12 +7001,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6452,17 +7023,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6579,7 +7153,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6591,6 +7166,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6605,6 +7181,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6612,12 +7189,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6636,6 +7215,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6716,7 +7296,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6728,6 +7309,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6813,7 +7395,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6849,6 +7432,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6868,6 +7452,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6911,12 +7496,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -7029,9 +7616,9 @@ } }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7221,9 +7808,9 @@ } }, "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "grapheme-splitter": { @@ -7238,6 +7825,12 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, "gulp": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", @@ -7250,15 +7843,6 @@ "vinyl-fs": "^3.0.0" }, "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", @@ -7318,12 +7902,6 @@ "yargs": "^7.1.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -7333,15 +7911,6 @@ "number-is-nan": "^1.0.0" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -7452,6 +8021,16 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "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.1", + "strip-ansi": "^3.0.1" + } + }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", @@ -8111,9 +8690,9 @@ } }, "handlebars": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.3.1.tgz", - "integrity": "sha512-c0HoNHzDiHpBt4Kqe99N8tdLPKAnGCQ73gYMPWtAYM4PwGnf7xl8PBUHJqh9ijlzt2uQKaSRxbXRt+rZ7M2/kA==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz", + "integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -8350,15 +8929,15 @@ "dev": true }, "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "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.15.10", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", - "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==", + "version": "9.16.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.16.2.tgz", + "integrity": "sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw==", "dev": true }, "hmac-drbg": { @@ -8398,11 +8977,20 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, "html-void-elements": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.4.tgz", @@ -8470,9 +9058,9 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -8517,6 +9105,16 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -8588,6 +9186,16 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -8625,9 +9233,9 @@ } }, "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "ipaddr.js": { @@ -8715,6 +9323,15 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -8814,6 +9431,12 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -9000,9 +9623,9 @@ "dev": true }, "is-wsl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", - "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, "isarray": { @@ -9060,12 +9683,31 @@ "wordwrap": "^1.0.0" }, "dependencies": { + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + } + }, "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -9091,6 +9733,16 @@ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", @@ -9099,6 +9751,12 @@ "requires": { "has-flag": "^1.0.0" } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true } } }, @@ -9108,162 +9766,763 @@ "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, "requires": { - "async": "^2.1.4", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.1", - "istanbul-lib-hook": "^1.2.2", - "istanbul-lib-instrument": "^1.10.2", - "istanbul-lib-report": "^1.1.5", - "istanbul-lib-source-maps": "^1.2.6", - "istanbul-reports": "^1.5.1", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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 + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "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-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, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + } + } + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" }, "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "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==", + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", "dev": true, "requires": { - "convert-source-map": "^1.5.0", - "istanbul-lib-instrument": "^1.7.3", - "loader-utils": "^1.1.0", - "schema-utils": "^0.3.0" + "@jest/types": "^24.9.0" } }, - "istanbul-lib-coverage": { + "jest-pnp-resolver": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", "dev": true }, - "istanbul-lib-hook": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", - "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", "dev": true, "requires": { - "append-transform": "^0.4.0" + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" } }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", "dev": true, "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" } }, - "istanbul-lib-report": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", - "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", "dev": true, "requires": { - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" }, "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } } } }, - "istanbul-lib-source-maps": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", - "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", "dev": true, "requires": { - "glob": "^7.1.3" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" } } } }, - "istanbul-reports": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", - "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", "dev": true, "requires": { - "handlebars": "^4.0.3" + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "istextorbinary": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", - "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", "dev": true, "requires": { - "binaryextensions": "2", - "editions": "^1.3.3", - "textextensions": "2" + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, - "isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", "dev": true, "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "js-levenshtein": { @@ -9294,6 +10553,40 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, "jsencrypt": { "version": "3.0.0-rc.1", "resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.0.0-rc.1.tgz", @@ -9348,9 +10641,9 @@ "dev": true }, "json5": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", - "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -9439,15 +10732,6 @@ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9518,6 +10802,14 @@ "dev": true, "requires": { "is-wsl": "^2.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", + "dev": true + } } }, "karma-ie-launcher": { @@ -9654,6 +10946,12 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "last-run": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", @@ -9680,12 +10978,12 @@ } }, "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "^2.0.0" + "invert-kv": "^1.0.0" } }, "lcov-parse": { @@ -9703,6 +11001,18 @@ "flush-write-stream": "^1.0.2" } }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -9982,6 +11292,12 @@ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.template": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", @@ -10167,13 +11483,13 @@ "kind-of": "^6.0.2" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", "dev": true, "requires": { - "p-defer": "^1.0.0" + "tmpl": "1.0.x" } }, "map-cache": { @@ -10367,22 +11683,12 @@ "dev": true }, "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "dependencies": { - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - } + "mimic-fn": "^1.0.0" } }, "memoizee": { @@ -10532,13 +11838,10 @@ "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.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "methods": { "version": "1.1.2", @@ -10599,9 +11902,9 @@ } }, "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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": { @@ -10729,12 +12032,6 @@ "path-is-absolute": "^1.0.0" } }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -10953,9 +12250,9 @@ }, "dependencies": { "@sinonjs/formatio": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", - "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", "dev": true, "requires": { "@sinonjs/commons": "^1", @@ -10970,15 +12267,11 @@ } } }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true }, "node-libs-browser": { "version": "2.2.1", @@ -11030,13 +12323,40 @@ } } }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, "node-releases": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.32.tgz", - "integrity": "sha512-VhVknkitq8dqtWoluagsGPn3dxTvN9fwgR59fV3D7sLBHe0JfDramsMI8n8mY//ccq/Kkrf8ZRHRpsyVZ3qw1A==", + "version": "1.1.39", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz", + "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==", "dev": true, "requires": { - "semver": "^5.3.0" + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "nopt": { @@ -11131,6 +12451,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -11322,14 +12648,6 @@ "dev": true, "requires": { "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - } } }, "opener": { @@ -11345,14 +12663,6 @@ "dev": true, "requires": { "is-wsl": "^1.1.0" - }, - "dependencies": { - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - } } }, "optimist": { @@ -11370,12 +12680,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true } } }, @@ -11391,6 +12695,14 @@ "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } } }, "ordered-read-streams": { @@ -11415,14 +12727,42 @@ "dev": true }, "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } } }, "os-tmpdir": { @@ -11437,11 +12777,14 @@ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, - "p-defer": { + "p-each-series": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } }, "p-finally": { "version": "1.0.0", @@ -11473,6 +12816,12 @@ "p-limit": "^2.0.0" } }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", @@ -11518,138 +12867,15 @@ } }, "parse-domain": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.2.tgz", - "integrity": "sha512-ywE9/YZwJZ8b2viJybvAyu9xO+4qbuLr0Jx73zoL8bHsDdDrFKWKGJKKEuvyNT0ZN1whQGnUAwdQMnsU0dqlPA==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-2.3.4.tgz", + "integrity": "sha512-LlFJJVTry4DD3Xa76CsVNP6MIu3JZ8GXd5HEEp38KSDGBCVsnccagAJ5YLy7uEEabvwtauQEQPcvXWgUGkJbMA==", "dev": true, "requires": { - "chai": "^4.2.0", "got": "^8.3.2", + "jest": "^24.9.0", "mkdirp": "^0.5.1", - "mocha": "^6.1.4", "npm-run-all": "^4.1.5" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } - } } }, "parse-entities": { @@ -11759,6 +12985,12 @@ "protocols": "^1.4.0" } }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -11953,6 +13185,15 @@ "pinkie": "^2.0.0" } }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -11972,17 +13213,6 @@ "arr-diff": "^4.0.0", "arr-union": "^3.1.0", "extend-shallow": "^3.0.2" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - } } }, "pluralize": { @@ -11991,6 +13221,12 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -12015,6 +13251,26 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -12045,6 +13301,16 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "prompts": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.2.1.tgz", + "integrity": "sha512-VObPvJiWPhpZI6C5m60XOzTfnYg/xc/an+r9VYymj9WJW3B/DIH+REzjpAACPf8brwPeP+7vz3bIim3S+AaMjw==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.3" + } + }, "property-information": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz", @@ -12188,9 +13454,9 @@ "dev": true }, "querystringify": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.3.tgz", - "integrity": "sha1-DJ02+/jHpPces3CFd2NXemMzW+c=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true }, "randomatic": { @@ -12255,6 +13521,12 @@ } } }, + "react-is": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz", + "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==", + "dev": true + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -12347,6 +13619,15 @@ "readable-stream": "^2.0.2" } }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -12435,9 +13716,9 @@ } }, "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", "dev": true }, "regjsparser": { @@ -12669,24 +13950,35 @@ } }, "request-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", - "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.5.tgz", + "integrity": "sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg==", "dev": true, "requires": { "bluebird": "^3.5.0", - "request-promise-core": "1.1.2", + "request-promise-core": "1.1.3", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" } }, "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", "dev": true, "requires": { - "lodash": "^4.17.11" + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "require-directory": { @@ -12734,6 +14026,23 @@ "path-parse": "^1.0.6" } }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, "resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", @@ -12812,10 +14121,13 @@ } }, "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } }, "ripemd160": { "version": "2.0.2", @@ -12827,6 +14139,12 @@ "inherits": "^2.0.1" } }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -12884,6 +14202,29 @@ "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, "schema-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", @@ -13150,6 +14491,12 @@ "rechoir": "^0.6.2" } }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -13179,6 +14526,12 @@ } } }, + "sisteransi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.3.tgz", + "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==", + "dev": true + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -13578,6 +14931,12 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, "state-toggle": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", @@ -13738,19 +15097,13 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "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": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", + "astral-regex": "^1.0.0", "strip-ansi": "^4.0.0" }, "dependencies": { @@ -13771,6 +15124,40 @@ } } }, + "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": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "string.prototype.padend": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", @@ -13893,6 +15280,12 @@ "es6-symbol": "^3.1.1" } }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", @@ -13905,6 +15298,33 @@ "lodash": "^4.17.4", "slice-ansi": "1.0.0", "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "tapable": { @@ -13958,6 +15378,41 @@ "fork-stream": "^0.0.4", "merge-stream": "^1.0.0", "through2": "^2.0.1" + }, + "dependencies": { + "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.0.1" + } + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + } } }, "text-table": { @@ -13972,6 +15427,12 @@ "integrity": "sha512-1IkVr355eHcomgK7fgj1Xsokturx6L5S2JRT5WcRdA6v5shk9sxWuO/w/VbpQexwkXJMQIa/j1dBi3oo7+HhcA==", "dev": true }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -14063,6 +15524,12 @@ "os-tmpdir": "~1.0.2" } }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", @@ -14172,6 +15639,15 @@ } } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -14273,12 +15749,12 @@ "dev": true }, "uglify-js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", - "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.7.tgz", + "integrity": "sha512-4sXQDzmdnoXiO+xvmTzQsfIiwrjUCSA95rSP4SEd8tDb51W2TiDOlL76Hl+Kw0Ie42PSItCW8/t6pBNCF2R48A==", "dev": true, "requires": { - "commander": "~2.20.0", + "commander": "~2.20.3", "source-map": "~0.6.1" }, "dependencies": { @@ -14623,14 +16099,6 @@ "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" - }, - "dependencies": { - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", - "dev": true - } } }, "url-parse-lax": { @@ -14695,6 +16163,16 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -14913,9 +16391,9 @@ } }, "vm-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, "void-elements": { @@ -14924,6 +16402,15 @@ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, "walk": { "version": "2.3.14", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", @@ -14933,6 +16420,15 @@ "foreachasync": "^3.0.0" } }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -15047,6 +16543,12 @@ } } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, "webpack": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", @@ -15095,6 +16597,12 @@ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "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.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -15134,32 +16642,6 @@ } } }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -15187,12 +16669,6 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -15214,15 +16690,6 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -15245,32 +16712,6 @@ "path-exists": "^3.0.0" } }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -15346,6 +16787,33 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "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" + }, + "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 + }, + "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", @@ -15355,6 +16823,29 @@ "has-flag": "^2.0.0" } }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", @@ -15394,9 +16885,9 @@ } }, "webpack-bundle-analyzer": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.5.1.tgz", - "integrity": "sha512-CDdaT3TTu4F9X3tcDq6PNJOiNGgREOM0WdN2vVAoUUn+M6NLB5kJ543HImCWbrDwOpbpGARSwU8r+u0Pl367kA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz", + "integrity": "sha512-orUfvVYEfBMDXgEKAKVvab5iQ2wXneIEorGNsyuOyVYpjYrI7CUOhhXNDd3huMwQ3vNNWWlGP+hzflMFYNzi2g==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -16095,6 +17586,32 @@ "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", "dev": true }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -16110,15 +17627,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -16126,39 +17634,35 @@ "dev": true }, "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "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=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "ansi-regex": "^4.1.0" } } } @@ -16178,15 +17682,24 @@ "mkdirp": "^0.5.1" } }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "async-limiter": "~1.0.0" } }, "x-is-string": { @@ -16195,6 +17708,12 @@ "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", "dev": true }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", @@ -16226,70 +17745,15 @@ "dev": true }, "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, - "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index 01aaa244e1f..2cb785c6a32 100755 --- a/package.json +++ b/package.json @@ -79,7 +79,6 @@ "lodash": "^4.17.4", "mocha": "^5.0.0", "opn": "^5.4.0", - "querystringify": "0.0.3", "resolve-from": "^5.0.0", "sinon": "^4.1.3", "through2": "^2.0.3", diff --git a/test/spec/modules/polluxBidAdapter_spec.js b/test/spec/modules/polluxBidAdapter_spec.js index ad30771e15b..22c7f470f83 100644 --- a/test/spec/modules/polluxBidAdapter_spec.js +++ b/test/spec/modules/polluxBidAdapter_spec.js @@ -2,6 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/polluxBidAdapter'; import {utils} from 'src/utils'; import {newBidder} from 'src/adapters/bidderFactory'; +import { parseQS } from 'src/url'; describe('POLLUX Bid Adapter tests', function () { // ad units setup @@ -178,13 +179,12 @@ describe('POLLUX Bid Adapter tests', function () { it('TEST: verify url and query params', function () { const URL = require('url-parse'); - const querystringify = require('querystringify'); const request = spec.buildRequests(setup_single_bid); const parsedUrl = new URL('https:' + request.url); expect(parsedUrl.origin).to.equal('https://adn.polluxnetwork.com'); expect(parsedUrl.pathname).to.equal('/prebid/v1'); expect(parsedUrl).to.have.property('query'); - const parsedQuery = querystringify.parse(parsedUrl.query); + const parsedQuery = parseQS(parsedUrl.query); expect(parsedQuery).to.have.property('domain').and.to.have.length.above(1); }); From 94db31f1af77940fdd3c710ce86037dfa9f2ac8a Mon Sep 17 00:00:00 2001 From: omerBrowsi <54346241+omerBrowsi@users.noreply.github.com> Date: Wed, 6 Nov 2019 21:46:07 +0200 Subject: [PATCH 376/436] Browsi real time data module (#4114) * real time data module, browsi sub module for real time data, new hook bidsBackCallback, fix for config unsubscribe * change timeout&primary ad server only to auctionDelay update docs * support multiple providers * change promise to callbacks configure submodule on submodules.json * bug fixes * use Prebid ajax * tests fix --- modules/.submodules.json | 3 + modules/browsiRtdProvider.js | 253 +++++++++++++++++++++++ modules/rtdModule/index.js | 211 +++++++++++++++++++ modules/rtdModule/provider.md | 27 +++ modules/rtdModule/realTimeData.md | 32 +++ src/auction.js | 52 +++-- src/config.js | 5 +- test/spec/modules/realTimeModule_spec.js | 193 +++++++++++++++++ 8 files changed, 752 insertions(+), 24 deletions(-) create mode 100644 modules/browsiRtdProvider.js create mode 100644 modules/rtdModule/index.js create mode 100644 modules/rtdModule/provider.md create mode 100644 modules/rtdModule/realTimeData.md create mode 100644 test/spec/modules/realTimeModule_spec.js diff --git a/modules/.submodules.json b/modules/.submodules.json index 130e7e8817e..214fb56f996 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -10,5 +10,8 @@ "adpod": [ "freeWheelAdserverVideo", "dfpAdServerVideo" + ], + "rtdModule": [ + "browsiRtdProvider" ] } diff --git a/modules/browsiRtdProvider.js b/modules/browsiRtdProvider.js new file mode 100644 index 00000000000..795c9c86f1e --- /dev/null +++ b/modules/browsiRtdProvider.js @@ -0,0 +1,253 @@ +/** + * This module adds browsi provider to the eal time data module + * The {@link module:modules/realTimeData} module is required + * The module will fetch predictions from browsi server + * The module will place browsi bootstrap script on page + * @module modules/browsiProvider + * @requires module:modules/realTimeData + */ + +/** + * @typedef {Object} ModuleParams + * @property {string} siteKey + * @property {string} pubKey + * @property {string} url + * @property {?string} keyName + * @property {number} auctionDelay + */ + +import {config} from '../src/config.js'; +import * as utils from '../src/utils'; +import {submodule} from '../src/hook'; +import {ajax} from '../src/ajax'; + +/** @type {string} */ +const MODULE_NAME = 'realTimeData'; +/** @type {ModuleParams} */ +let _moduleParams = {}; +/** @type {null|Object} */ +let _data = null; +/** @type {null | function} */ +let _dataReadyCallback = null; + +/** + * add browsi script to page + * @param {string} bptUrl + */ +export function addBrowsiTag(bptUrl) { + let script = document.createElement('script'); + script.async = true; + script.setAttribute('data-sitekey', _moduleParams.siteKey); + script.setAttribute('data-pubkey', _moduleParams.pubKey); + script.setAttribute('prebidbpt', 'true'); + script.setAttribute('id', 'browsi-tag'); + script.setAttribute('src', bptUrl); + document.head.appendChild(script); + return script; +} + +/** + * collect required data from page + * send data to browsi server to get predictions + */ +function collectData() { + const win = window.top; + const doc = win.document; + let browsiData = null; + try { + browsiData = utils.getDataFromLocalStorage('__brtd'); + } catch (e) { + utils.logError('unable to parse __brtd'); + } + + let predictorData = { + ...{ + sk: _moduleParams.siteKey, + sw: (win.screen && win.screen.width) || -1, + sh: (win.screen && win.screen.height) || -1, + url: encodeURIComponent(`${doc.location.protocol}//${doc.location.host}${doc.location.pathname}`), + }, + ...(browsiData ? {us: browsiData} : {us: '{}'}), + ...(document.referrer ? {r: document.referrer} : {}), + ...(document.title ? {at: document.title} : {}) + }; + getPredictionsFromServer(`//${_moduleParams.url}/prebid?${toUrlParams(predictorData)}`); +} + +export function setData(data) { + _data = data; + + if (typeof _dataReadyCallback === 'function') { + _dataReadyCallback(_data); + _dataReadyCallback = null; + } +} + +/** + * wait for data from server + * call callback when data is ready + * @param {function} callback + */ +function waitForData(callback) { + if (_data) { + _dataReadyCallback = null; + callback(_data); + } else { + _dataReadyCallback = callback; + } +} + +/** + * filter server data according to adUnits received + * call callback (onDone) when data is ready + * @param {adUnit[]} adUnits + * @param {function} onDone callback function + */ +function sendDataToModule(adUnits, onDone) { + try { + waitForData(_predictionsData => { + const _predictions = _predictionsData.p; + if (!_predictions || !Object.keys(_predictions).length) { + return onDone({}); + } + const slots = getAllSlots(); + if (!slots) { + return onDone({}); + } + let dataToReturn = adUnits.reduce((rp, cau) => { + const adUnitCode = cau && cau.code; + if (!adUnitCode) { return rp } + const predictionData = _predictions[adUnitCode]; + if (!predictionData) { return rp } + + if (predictionData.p) { + if (!isIdMatchingAdUnit(adUnitCode, slots, predictionData.w)) { + return rp; + } + rp[adUnitCode] = getKVObject(predictionData.p, _predictionsData.kn); + } + return rp; + }, {}); + return onDone(dataToReturn); + }); + } catch (e) { + onDone({}); + } +} + +/** + * get all slots on page + * @return {Object[]} slot GoogleTag slots + */ +function getAllSlots() { + return utils.isGptPubadsDefined && window.googletag.pubads().getSlots(); +} +/** + * get prediction and return valid object for key value set + * @param {number} p + * @param {string?} keyName + * @return {Object} key:value + */ +function getKVObject(p, keyName) { + const prValue = p < 0 ? 'NA' : (Math.floor(p * 10) / 10).toFixed(2); + let prObject = {}; + prObject[((_moduleParams['keyName'] || keyName).toString())] = prValue.toString(); + return prObject; +} +/** + * check if placement id matches one of given ad units + * @param {number} id placement id + * @param {Object[]} allSlots google slots on page + * @param {string[]} whitelist ad units + * @return {boolean} + */ +export function isIdMatchingAdUnit(id, allSlots, whitelist) { + if (!whitelist || !whitelist.length) { + return true; + } + const slot = allSlots.filter(s => s.getSlotElementId() === id); + const slotAdUnits = slot.map(s => s.getAdUnitPath()); + return slotAdUnits.some(a => whitelist.indexOf(a) !== -1); +} + +/** + * XMLHttpRequest to get data form browsi server + * @param {string} url server url with query params + */ +function getPredictionsFromServer(url) { + ajax(url, + { + success: function (response, req) { + if (req.status === 200) { + try { + const data = JSON.parse(response); + if (data && data.p && data.kn) { + setData({p: data.p, kn: data.kn}); + } else { + setData({}); + } + addBrowsiTag(data.u); + } catch (err) { + utils.logError('unable to parse data'); + setData({}) + } + } else if (req.status === 204) { + // unrecognized site key + setData({}); + } + }, + error: function () { + setData({}); + utils.logError('unable to get prediction data'); + } + } + ); +} + +/** + * serialize object and return query params string + * @param {Object} data + * @return {string} + */ +function toUrlParams(data) { + return Object.keys(data) + .map(key => key + '=' + encodeURIComponent(data[key])) + .join('&'); +} + +/** @type {RtdSubmodule} */ +export const browsiSubmodule = { + /** + * used to link submodule with realTimeData + * @type {string} + */ + name: 'browsi', + /** + * get data and send back to realTimeData module + * @function + * @param {adUnit[]} adUnits + * @param {function} onDone + */ + getData: sendDataToModule +}; + +export function init(config) { + const confListener = config.getConfig(MODULE_NAME, ({realTimeData}) => { + try { + _moduleParams = realTimeData.dataProviders && realTimeData.dataProviders.filter( + pr => pr.name && pr.name.toLowerCase() === 'browsi')[0].params; + _moduleParams.auctionDelay = realTimeData.auctionDelay; + } catch (e) { + _moduleParams = {}; + } + if (_moduleParams.siteKey && _moduleParams.pubKey && _moduleParams.url) { + confListener(); + collectData(); + } else { + utils.logError('missing params for Browsi provider'); + } + }); +} + +submodule('realTimeData', browsiSubmodule); +init(config); diff --git a/modules/rtdModule/index.js b/modules/rtdModule/index.js new file mode 100644 index 00000000000..e7ba364c0e5 --- /dev/null +++ b/modules/rtdModule/index.js @@ -0,0 +1,211 @@ +/** + * This module adds Real time data support to prebid.js + * @module modules/realTimeData + */ + +/** + * @interface RtdSubmodule + */ + +/** + * @function + * @summary return real time data + * @name RtdSubmodule#getData + * @param {AdUnit[]} adUnits + * @param {function} onDone + */ + +/** + * @property + * @summary used to link submodule with config + * @name RtdSubmodule#name + * @type {string} + */ + +/** + * @interface ModuleConfig + */ + +/** + * @property + * @summary sub module name + * @name ModuleConfig#name + * @type {string} + */ + +/** + * @property + * @summary auction delay + * @name ModuleConfig#auctionDelay + * @type {number} + */ + +/** + * @property + * @summary params for provide (sub module) + * @name ModuleConfig#params + * @type {Object} + */ + +import {getGlobal} from '../../src/prebidGlobal'; +import {config} from '../../src/config.js'; +import {targeting} from '../../src/targeting'; +import {getHook, module} from '../../src/hook'; +import * as utils from '../../src/utils'; + +/** @type {string} */ +const MODULE_NAME = 'realTimeData'; +/** @type {RtdSubmodule[]} */ +let subModules = []; +/** @type {ModuleConfig} */ +let _moduleConfig; + +/** + * enable submodule in User ID + * @param {RtdSubmodule} submodule + */ +export function attachRealTimeDataProvider(submodule) { + subModules.push(submodule); +} + +export function init(config) { + const confListener = config.getConfig(MODULE_NAME, ({realTimeData}) => { + if (!realTimeData.dataProviders) { + utils.logError('missing parameters for real time module'); + return; + } + confListener(); // unsubscribe config listener + _moduleConfig = realTimeData; + if (typeof (_moduleConfig.auctionDelay) === 'undefined') { + _moduleConfig.auctionDelay = 0; + } + // delay bidding process only if auctionDelay > 0 + if (!_moduleConfig.auctionDelay > 0) { + getHook('bidsBackCallback').before(setTargetsAfterRequestBids); + } else { + getGlobal().requestBids.before(requestBidsHook); + } + }); +} + +/** + * get data from sub module + * @param {AdUnit[]} adUnits received from auction + * @param {function} callback callback function on data received + */ +function getProviderData(adUnits, callback) { + const callbackExpected = subModules.length; + let dataReceived = []; + let processDone = false; + const dataWaitTimeout = setTimeout(() => { + processDone = true; + callback(dataReceived); + }, _moduleConfig.auctionDelay); + + subModules.forEach(sm => { + sm.getData(adUnits, onDataReceived); + }); + + function onDataReceived(data) { + if (processDone) { + return + } + dataReceived.push(data); + if (dataReceived.length === callbackExpected) { + processDone = true; + clearTimeout(dataWaitTimeout); + callback(dataReceived); + } + } +} + +/** + * run hook after bids request and before callback + * get data from provider and set key values to primary ad server + * @param {function} next - next hook function + * @param {AdUnit[]} adUnits received from auction + */ +export function setTargetsAfterRequestBids(next, adUnits) { + getProviderData(adUnits, (data) => { + if (data && Object.keys(data).length) { + const _mergedData = deepMerge(data); + if (Object.keys(_mergedData).length) { + setDataForPrimaryAdServer(_mergedData); + } + } + next(adUnits); + }); +} + +/** + * deep merge array of objects + * @param {array} arr - objects array + * @return {Object} merged object + */ +export function deepMerge(arr) { + if (!Array.isArray(arr) || !arr.length) { + return {}; + } + return arr.reduce((merged, obj) => { + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + if (!merged.hasOwnProperty(key)) merged[key] = obj[key]; + else { + // duplicate key - merge values + const dp = obj[key]; + for (let dk in dp) { + if (dp.hasOwnProperty(dk)) merged[key][dk] = dp[dk]; + } + } + } + } + return merged; + }, {}); +} + +/** + * run hook before bids request + * get data from provider and set key values to primary ad server & bidders + * @param {function} fn - hook function + * @param {Object} reqBidsConfigObj - request bids object + */ +export function requestBidsHook(fn, reqBidsConfigObj) { + getProviderData(reqBidsConfigObj.adUnits || getGlobal().adUnits, (data) => { + if (data && Object.keys(data).length) { + const _mergedData = deepMerge(data); + if (Object.keys(_mergedData).length) { + setDataForPrimaryAdServer(_mergedData); + addIdDataToAdUnitBids(reqBidsConfigObj.adUnits || getGlobal().adUnits, _mergedData); + } + } + return fn.call(this, reqBidsConfigObj); + }); +} + +/** + * set data to primary ad server + * @param {Object} data - key values to set + */ +function setDataForPrimaryAdServer(data) { + if (!utils.isGptPubadsDefined()) { + utils.logError('window.googletag is not defined on the page'); + return; + } + targeting.setTargetingForGPT(data, null); +} + +/** + * @param {AdUnit[]} adUnits + * @param {Object} data - key values to set + */ +function addIdDataToAdUnitBids(adUnits, data) { + adUnits.forEach(adUnit => { + adUnit.bids = adUnit.bids.map(bid => { + const rd = data[adUnit.code] || {}; + return Object.assign(bid, {realTimeData: rd}); + }) + }); +} + +init(config); +module('realTimeData', attachRealTimeDataProvider); diff --git a/modules/rtdModule/provider.md b/modules/rtdModule/provider.md new file mode 100644 index 00000000000..fb42e7188d3 --- /dev/null +++ b/modules/rtdModule/provider.md @@ -0,0 +1,27 @@ +New provider must include the following: + +1. sub module object: +``` +export const subModuleName = { + name: String, + getData: Function +}; +``` + +2. Function that returns the real time data according to the following structure: +``` +{ + "adUnitCode":{ + "key":"value", + "key2":"value" + }, + "adUnitCode2":{ + "dataKey":"dataValue", + } +} +``` + +3. Hook to Real Time Data module: +``` +submodule('realTimeData', subModuleName); +``` diff --git a/modules/rtdModule/realTimeData.md b/modules/rtdModule/realTimeData.md new file mode 100644 index 00000000000..b2859098b1f --- /dev/null +++ b/modules/rtdModule/realTimeData.md @@ -0,0 +1,32 @@ +## Real Time Data Configuration Example + +Example showing config using `browsi` sub module +``` + pbjs.setConfig({ + "realTimeData": { + "auctionDelay": 1000, + dataProviders[{ + "name": "browsi", + "params": { + "url": "testUrl.com", + "siteKey": "testKey", + "pubKey": "testPub", + "keyName":"bv" + } + }] + } + }); +``` + +Example showing real time data object received form `browsi` real time data provider +``` +{ + "adUnitCode":{ + "key":"value", + "key2":"value" + }, + "adUnitCode2":{ + "dataKey":"dataValue", + } +} +``` diff --git a/src/auction.js b/src/auction.js index fd29aec4b16..9b6951c6b7a 100644 --- a/src/auction.js +++ b/src/auction.js @@ -154,29 +154,31 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a _auctionEnd = Date.now(); events.emit(CONSTANTS.EVENTS.AUCTION_END, getProperties()); - try { - if (_callback != null) { - const adUnitCodes = _adUnitCodes; - const bids = _bidsReceived - .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) - .reduce(groupByPlacement, {}); - _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); - _callback = null; - } - } catch (e) { - utils.logError('Error executing bidsBackHandler', null, e); - } finally { - // 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) { - // Delay the auto sync by the config delay - syncUsers(userSyncConfig.syncDelay); + bidsBackCallback(_adUnitCodes, function () { + try { + if (_callback != null) { + const adUnitCodes = _adUnitCodes; + const bids = _bidsReceived + .filter(utils.bind.call(adUnitsFilter, this, adUnitCodes)) + .reduce(groupByPlacement, {}); + _callback.apply($$PREBID_GLOBAL$$, [bids, timedOut]); + _callback = null; + } + } catch (e) { + utils.logError('Error executing bidsBackHandler', null, e); + } finally { + // 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) { + // Delay the auto sync by the config delay + syncUsers(userSyncConfig.syncDelay); + } } - } + }) } } @@ -328,6 +330,12 @@ export const addBidResponse = hook('async', function(adUnitCode, bid) { this.dispatch.call(this.bidderRequest, adUnitCode, bid); }, 'addBidResponse'); +export const bidsBackCallback = hook('async', function (adUnits, callback) { + if (callback) { + callback(); + } +}, 'bidsBackCallback'); + export function auctionCallbacks(auctionDone, auctionInstance) { let outstandingBidsAdded = 0; let allAdapterCalledDone = false; diff --git a/src/config.js b/src/config.js index ec26c3d51d0..022f29dd8c1 100644 --- a/src/config.js +++ b/src/config.js @@ -300,11 +300,12 @@ export function newConfig() { return; } - listeners.push({ topic, callback }); + const nl = { topic, callback }; + listeners.push(nl); // save and call this function to remove the listener return function unsubscribe() { - listeners.splice(listeners.indexOf(listener), 1); + listeners.splice(listeners.indexOf(nl), 1); }; } diff --git a/test/spec/modules/realTimeModule_spec.js b/test/spec/modules/realTimeModule_spec.js new file mode 100644 index 00000000000..807781d5a9c --- /dev/null +++ b/test/spec/modules/realTimeModule_spec.js @@ -0,0 +1,193 @@ +import { + init, + requestBidsHook, + setTargetsAfterRequestBids, + deepMerge +} from 'modules/rtdModule/index'; +import { + init as browsiInit, + addBrowsiTag, + isIdMatchingAdUnit, + setData +} from 'modules/browsiRtdProvider'; +import {config} from 'src/config'; +import {makeSlot} from '../integration/faker/googletag'; + +let expect = require('chai').expect; + +describe('Real time module', function() { + const conf = { + 'realTimeData': { + 'auctionDelay': 250, + dataProviders: [{ + 'name': 'browsi', + 'params': { + 'url': 'testUrl.com', + 'siteKey': 'testKey', + 'pubKey': 'testPub', + 'keyName': 'bv' + } + }] + + } + }; + + const predictions = + {p: { + 'browsiAd_2': { + 'w': [ + '/57778053/Browsi_Demo_Low', + '/57778053/Browsi_Demo_300x250' + ], + 'p': 0.07 + }, + 'browsiAd_1': { + 'w': [], + 'p': 0.06 + }, + 'browsiAd_3': { + 'w': [], + 'p': 0.53 + }, + 'browsiAd_4': { + 'w': [ + '/57778053/Browsi_Demo' + ], + 'p': 0.85 + } + } + }; + + function getAdUnitMock(code = 'adUnit-code') { + return { + code, + mediaTypes: {banner: {}, native: {}}, + sizes: [[300, 200], [300, 600]], + bids: [{bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}}] + }; + } + + function createSlots() { + const slot1 = makeSlot({code: '/57778053/Browsi_Demo_300x250', divId: 'browsiAd_1'}); + return [slot1]; + } + + describe('Real time module with browsi provider', function() { + afterEach(function () { + $$PREBID_GLOBAL$$.requestBids.removeAll(); + }); + + it('check module using bidsBackCallback', function () { + let adUnits1 = [getAdUnitMock('browsiAd_1')]; + let targeting = []; + init(config); + browsiInit(config); + config.setConfig(conf); + setData(predictions); + + // set slot + const slots = createSlots(); + window.googletag.pubads().setSlots(slots); + + function afterBidHook() { + slots.map(s => { + targeting = []; + s.getTargeting().map(value => { + targeting.push(Object.keys(value).toString()); + }); + }); + } + setTargetsAfterRequestBids(afterBidHook, adUnits1, true); + + setTimeout(() => { + expect(targeting.indexOf('bv')).to.be.greaterThan(-1); + }, 200); + }); + + it('check module using requestBidsHook', function () { + console.log('entrance', new Date().getMinutes() + ':' + new Date().getSeconds()); + let adUnits1 = [getAdUnitMock('browsiAd_1')]; + let targeting = []; + let dataReceived = null; + + // set slot + const slotsB = createSlots(); + window.googletag.pubads().setSlots(slotsB); + + function afterBidHook(data) { + dataReceived = data; + slotsB.map(s => { + targeting = []; + s.getTargeting().map(value => { + targeting.push(Object.keys(value).toString()); + }); + }); + } + requestBidsHook(afterBidHook, {adUnits: adUnits1}); + setTimeout(() => { + expect(targeting.indexOf('bv')).to.be.greaterThan(-1); + dataReceived.adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid.realTimeData).to.have.property('bv'); + }); + }); + }, 200); + }); + + it('check object deep merge', function () { + const obj1 = { + id1: { + key: 'value', + key2: 'value2' + }, + id2: { + k: 'v' + } + }; + const obj2 = { + id1: { + key3: 'value3' + } + }; + const obj3 = { + id3: { + key: 'value' + } + }; + const expected = { + id1: { + key: 'value', + key2: 'value2', + key3: 'value3' + }, + id2: { + k: 'v' + }, + id3: { + key: 'value' + } + }; + + const merged = deepMerge([obj1, obj2, obj3]); + assert.deepEqual(expected, merged); + }); + + it('check browsi sub module', function () { + const script = addBrowsiTag('scriptUrl.com'); + expect(script.getAttribute('data-sitekey')).to.equal('testKey'); + expect(script.getAttribute('data-pubkey')).to.equal('testPub'); + expect(script.async).to.equal(true); + + const slots = createSlots(); + const test1 = isIdMatchingAdUnit('browsiAd_1', slots, ['/57778053/Browsi_Demo_300x250']); // true + const test2 = isIdMatchingAdUnit('browsiAd_1', slots, ['/57778053/Browsi_Demo_300x250', '/57778053/Browsi']); // true + const test3 = isIdMatchingAdUnit('browsiAd_1', slots, ['/57778053/Browsi_Demo_Low']); // false + const test4 = isIdMatchingAdUnit('browsiAd_1', slots, []); // true + + expect(test1).to.equal(true); + expect(test2).to.equal(true); + expect(test3).to.equal(false); + expect(test4).to.equal(true); + }) + }); +}); From 96490e2d56901de0676a57bd676257e2ffe8cd39 Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 6 Nov 2019 15:51:00 -0500 Subject: [PATCH 377/436] Prebid 2.39.0 Release --- package-lock.json | 61 ++++++++++++++++------------------------------- package.json | 2 +- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index ffde0ad63ce..664cd7eebfc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.39.0-pre", + "version": "2.39.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4195,9 +4195,9 @@ "dev": true }, "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -5233,9 +5233,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.303", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.303.tgz", - "integrity": "sha512-xDFPmMjJ0gQBsVwspB0bjcbFn3MVcvU0sxXYmh1UMbZ6rDogQVM3vSyOvTO4rym1KlnJIU6nqzK3qs0yKudmjw==", + "version": "1.3.304", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.304.tgz", + "integrity": "sha512-a5mqa13jCdBc+Crgk3Gyr7vpXCiFWfFq23YDCEmrPYeiDOQKZDVE6EX/Q4Xdv97n3XkcjiSBDOY0IS19yP2yeA==", "dev": true }, "elliptic": { @@ -6979,8 +6979,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -7001,14 +7000,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7023,20 +7020,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -7153,8 +7147,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -7166,7 +7159,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7181,7 +7173,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7189,14 +7180,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7215,7 +7204,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7296,8 +7284,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7309,7 +7296,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7395,8 +7381,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7432,7 +7417,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7452,7 +7436,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7496,14 +7479,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -15749,9 +15730,9 @@ "dev": true }, "uglify-js": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.7.tgz", - "integrity": "sha512-4sXQDzmdnoXiO+xvmTzQsfIiwrjUCSA95rSP4SEd8tDb51W2TiDOlL76Hl+Kw0Ie42PSItCW8/t6pBNCF2R48A==", + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.8.tgz", + "integrity": "sha512-XhHJ3S3ZyMwP8kY1Gkugqx3CJh2C3O0y8NPiSxtm1tyD/pktLAkFZsFGpuNfTZddKDQ/bbDBLAd2YyA1pbi8HQ==", "dev": true, "requires": { "commander": "~2.20.3", diff --git a/package.json b/package.json index 2cb785c6a32..8562aaa439b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.39.0-pre", + "version": "2.39.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 4febd85891af94785b6a1215f76b922a4411168f Mon Sep 17 00:00:00 2001 From: Jason Snellbaker Date: Wed, 6 Nov 2019 16:06:04 -0500 Subject: [PATCH 378/436] increment pre version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 664cd7eebfc..84e5b08ea80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.39.0", + "version": "2.40.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8562aaa439b..00e47b4c312 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.39.0", + "version": "2.40.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 5652dde714e40bf712e37e335bf3c756fac19fc6 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Thu, 7 Nov 2019 11:50:03 -0800 Subject: [PATCH 379/436] OpenX Adapter: Prebid 3.0 Compatibility Update (#4413) * Removed usage of deprecated functions * Removed beacons * Banner sizes now reads from bidRequest.mediaTypes.banner.sizes instead of bidRequest.sizes * Updated tests to reflect changes. --- modules/openxBidAdapter.js | 73 +------ modules/openxoutstreamBidAdapter.js | 7 +- test/spec/modules/openxBidAdapter_spec.js | 191 +++++------------- .../modules/openxoutstreamBidAdapter_spec.js | 14 +- 4 files changed, 61 insertions(+), 224 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index a5c5b432a55..1e69dc01471 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -1,14 +1,13 @@ 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 {parse} from '../src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.9'; +const BIDDER_VERSION = '3.0.0'; const USER_ID_CODE_TO_QUERY_ARG = { idl_env: 'lre', // liveramp @@ -16,12 +15,6 @@ const USER_ID_CODE_TO_QUERY_ARG = { tdid: 'ttduuid' // the trade desk }; -let shouldSendBoPixel = true; - -export function resetBoPixel() { - shouldSendBoPixel = true; -} - export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, @@ -132,24 +125,10 @@ function createBannerBidResponses(oxResponseObj, {bids, startTime}) { } bidResponses.push(bidResponse); - - registerBeacon(BANNER, adUnit, startTime); } return bidResponses; } -function buildQueryStringFromParams(params) { - for (let key in params) { - if (params.hasOwnProperty(key)) { - if (!params[key]) { - delete params[key]; - } - } - } - return utils._map(Object.keys(params), key => `${key}=${params[key]}`) - .join('&'); -} - function getViewportDimensions(isIfr) { let width; let height; @@ -210,8 +189,7 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { let defaultParams; defaultParams = { - ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), - jr: utils.getTopWindowReferrer(), + ju: config.getConfig('pageUrl') || bidderRequest.refererInfo.referer, ch: document.charSet || document.characterSet, res: `${screen.width}x${screen.height}x${screen.colorDepth}`, ifr: isInIframe, @@ -285,7 +263,8 @@ function buildOXBannerRequest(bids, bidderRequest) { let hasCustomParam = false; let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); let auids = utils._map(bids, bid => bid.params.unit); - queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); + + queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.mediaTypes.banner.sizes).join(',')).join('|'); queryParams.divIds = utils._map(bids, bid => encodeURIComponent(bid.adUnitCode)).join(','); if (auids.some(auid => auid)) { @@ -425,53 +404,9 @@ function createVideoBidResponses(response, {bid, startTime}) { response.ts = vastQueryParams.ts; 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) { - 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 = `https://${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/modules/openxoutstreamBidAdapter.js b/modules/openxoutstreamBidAdapter.js index 9011a949e7b..b9760c0c3bb 100644 --- a/modules/openxoutstreamBidAdapter.js +++ b/modules/openxoutstreamBidAdapter.js @@ -6,7 +6,7 @@ import { BANNER } from '../src/mediaTypes'; const SUPPORTED_AD_TYPES = [BANNER]; const BIDDER_CODE = 'openxoutstream'; const BIDDER_CONFIG = 'hb_pb_ym'; -const BIDDER_VERSION = '1.0.0'; +const BIDDER_VERSION = '1.0.1'; const CURRENCY = 'USD'; const NET_REVENUE = true; const TIME_TO_LIVE = 300; @@ -70,8 +70,7 @@ function buildCommonQueryParamsFromBids(bid, bidderRequest) { const width = '414'; const aus = '304x184%7C412x184%7C375x184%7C414x184'; defaultParams = { - ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), - jr: utils.getTopWindowReferrer(), + ju: config.getConfig('pageUrl') || bidderRequest.refererInfo.referer, ch: document.charSet || document.characterSet, res: `${screen.width}x${screen.height}x${screen.colorDepth}`, ifr: isInIframe, @@ -118,7 +117,7 @@ function buildOXBannerRequest(bid, bidderRequest) { queryParams.tfcd = 1; } - let url = `https://${bid.params.delDomain}/v/1.0/avjp` + let url = `https://${bid.params.delDomain}/v/1.0/avjp`; return { method: 'GET', url: url, diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 0002d25c37d..353c3342627 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -234,12 +234,6 @@ describe('OpenxAdapter', function () { videoBidWithMediaTypes.params = {}; expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); }); - it('should send bid request to openx url via GET, with mediaType specified as video', function () { - const request = spec.buildRequests([videoBidWithMediaTypes]); - expect(request[0].url).to.equal(`https://${videoBidWithMediaTypes.params.delDomain}${URLBASEVIDEO}`); - expect(request[0].data.ph).to.be.undefined; - expect(request[0].method).to.equal('GET'); - }); }); describe('and request config uses both delDomain and platform', () => { const videoBidWithDelDomainAndPlatform = { @@ -269,12 +263,6 @@ describe('OpenxAdapter', function () { videoBidWithMediaTypes.params = {}; expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); }); - it('should send bid request to openx url via GET, with mediaType specified as video', function () { - const request = spec.buildRequests([videoBidWithDelDomainAndPlatform]); - expect(request[0].url).to.equal(`https://u.openx.net${URLBASEVIDEO}`); - expect(request[0].data.ph).to.equal(videoBidWithDelDomainAndPlatform.params.platform); - expect(request[0].method).to.equal('GET'); - }); }); describe('and request config uses mediaType', () => { const videoBidWithMediaType = { @@ -301,30 +289,11 @@ describe('OpenxAdapter', function () { videoBidWithMediaType.params = {}; expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(false); }); - it('should send bid request to openx url via GET, with mediaType specified as video', function () { - const request = spec.buildRequests([videoBidWithMediaType]); - expect(request[0].url).to.equal(`https://${videoBidWithMediaType.params.delDomain}${URLBASEVIDEO}`); - expect(request[0].data.ph).to.be.undefined; - expect(request[0].method).to.equal('GET'); - }); }); }); }); describe('buildRequests for banner ads', function () { - const bidRequestsWithMediaType = [{ - '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 bidRequestsWithMediaTypes = [{ 'bidder': 'openx', 'params': { @@ -356,6 +325,7 @@ describe('OpenxAdapter', function () { 'bidderRequestId': 'test-bid-request-2', 'auctionId': 'test-auction-2' }]; + const bidRequestsWithPlatform = [{ 'bidder': 'openx', 'params': { @@ -388,22 +358,17 @@ describe('OpenxAdapter', function () { 'auctionId': 'test-auction-1' }]; - it('should send bid request to openx url via GET, with mediaType specified as banner', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].url).to.equal('https://' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); - expect(request[0].data.ph).to.be.undefined; - expect(request[0].method).to.equal('GET'); - }); + const mockBidderRequest = {refererInfo: {}}; it('should send bid request to openx url via GET, with mediaTypes specified with banner type', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].url).to.equal('https://' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); expect(request[0].data.ph).to.be.undefined; expect(request[0].method).to.equal('GET'); }); it('should send bid request to openx platform url via GET, if platform is present', function () { - const request = spec.buildRequests(bidRequestsWithPlatform); + const request = spec.buildRequests(bidRequestsWithPlatform, mockBidderRequest); expect(request[0].url).to.equal(`https://u.openx.net${URLBASE}`); expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); expect(request[0].method).to.equal('GET'); @@ -444,14 +409,14 @@ describe('OpenxAdapter', function () { 'auctionId': 'test-auction-1' }]; - const request = spec.buildRequests(bidRequestsWithPlatformAndDelDomain); + const request = spec.buildRequests(bidRequestsWithPlatformAndDelDomain, mockBidderRequest); expect(request[0].url).to.equal(`https://u.openx.net${URLBASE}`); expect(request[0].data.ph).to.equal(bidRequestsWithPlatform[0].params.platform); expect(request[0].method).to.equal('GET'); }); it('should send the adunit codes', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].data.divIds).to.equal(`${encodeURIComponent(bidRequestsWithMediaTypes[0].adUnitCode)},${encodeURIComponent(bidRequestsWithMediaTypes[1].adUnitCode)}`); }); @@ -486,7 +451,7 @@ describe('OpenxAdapter', function () { 'bidderRequestId': 'test-bid-request-2', 'auctionId': 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithUnitIds); + const request = spec.buildRequests(bidRequestsWithUnitIds, mockBidderRequest); expect(request[0].data.auid).to.equal(`,${bidRequestsWithUnitIds[1].params.unit}`); }); @@ -520,39 +485,10 @@ describe('OpenxAdapter', function () { 'bidderRequestId': 'test-bid-request-2', 'auctionId': 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithoutUnitIds); + const request = spec.buildRequests(bidRequestsWithoutUnitIds, mockBidderRequest); expect(request[0].data).to.not.have.any.keys('auid'); }); - 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', function () { - 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', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], @@ -565,7 +501,7 @@ describe('OpenxAdapter', function () { } ); - const request = spec.buildRequests([bidRequest]); + const request = spec.buildRequests([bidRequest], mockBidderRequest); const dataParams = request[0].data; expect(dataParams.tps).to.exist; @@ -584,7 +520,7 @@ describe('OpenxAdapter', function () { } ); - const request = spec.buildRequests([bidRequest]); + const request = spec.buildRequests([bidRequest], mockBidderRequest); const dataParams = request[0].data; expect(dataParams.aumfs).to.exist; @@ -603,7 +539,7 @@ describe('OpenxAdapter', function () { } ); - const request = spec.buildRequests([bidRequest]); + const request = spec.buildRequests([bidRequest], mockBidderRequest); const dataParams = request[0].data; expect(dataParams.bc).to.exist; @@ -611,7 +547,7 @@ describe('OpenxAdapter', function () { }); it('should not send any consent management properties', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); 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); @@ -669,7 +605,8 @@ describe('OpenxAdapter', function () { gdprConsent: { consentString: 'test-gdpr-consent-string', gdprApplies: true - } + }, + refererInfo: {} }; mockConfig = { @@ -710,7 +647,8 @@ describe('OpenxAdapter', function () { gdprConsent: { consentString: 'test-gdpr-consent-string', gdprApplies: false - } + }, + refererInfo: {} }; mockConfig = { @@ -751,7 +689,8 @@ describe('OpenxAdapter', function () { gdprConsent: { consentString: 'test-gdpr-consent-string', gdprApplies: true - } + }, + refererInfo: {} }; mockConfig = { @@ -823,7 +762,7 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-2', auctionId: 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithoutCoppa); + const request = spec.buildRequests(bidRequestsWithoutCoppa, mockBidderRequest); expect(request[0].data).to.not.have.any.keys('tfcd'); }); @@ -861,7 +800,7 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-2', auctionId: 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithCoppa); + const request = spec.buildRequests(bidRequestsWithCoppa, mockBidderRequest); expect(request[0].data.tfcd).to.equal(1); }); @@ -898,7 +837,7 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-2', auctionId: 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithoutDnt); + const request = spec.buildRequests(bidRequestsWithoutDnt, mockBidderRequest); expect(request[0].data).to.not.have.any.keys('ns'); }); @@ -936,7 +875,7 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-2', auctionId: 'test-auction-2' }]; - const request = spec.buildRequests(bidRequestsWithDnt); + const request = spec.buildRequests(bidRequestsWithDnt, mockBidderRequest); expect(request[0].data.ns).to.equal(1); }); @@ -998,7 +937,7 @@ describe('OpenxAdapter', function () { }); it('should send a schain parameter with the proper delimiter symbols', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, mockBidderRequest); const dataParams = request[0].data; const numNodes = schainConfig.nodes.length; @@ -1011,7 +950,7 @@ describe('OpenxAdapter', function () { }); it('should send a schain with the right version', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, mockBidderRequest); const dataParams = request[0].data; let serializedSupplyChain = dataParams.schain.split('!'); let version = serializedSupplyChain.shift().split(',')[0]; @@ -1020,7 +959,7 @@ describe('OpenxAdapter', function () { }); it('should send a schain with the right complete value', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, mockBidderRequest); const dataParams = request[0].data; let serializedSupplyChain = dataParams.schain.split('!'); let isComplete = serializedSupplyChain.shift().split(',')[1]; @@ -1029,7 +968,7 @@ describe('OpenxAdapter', function () { }); it('should send all available params in the right order', function () { - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, mockBidderRequest); const dataParams = request[0].data; let serializedSupplyChain = dataParams.schain.split('!'); serializedSupplyChain.shift(); @@ -1051,7 +990,7 @@ describe('OpenxAdapter', function () { describe('when there are userid providers', function () { describe('with publisher common id', function () { it('should not send a pubcid query param when there is no crumbs.pubcid and no userId.pubcid defined in the bid requests', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].data).to.not.have.any.keys('pubcid'); }); @@ -1075,7 +1014,7 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1' }]; - const request = spec.buildRequests(bidRequestsWithPubcid); + const request = spec.buildRequests(bidRequestsWithPubcid, mockBidderRequest); expect(request[0].data.pubcid).to.equal('c4a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); }); @@ -1099,14 +1038,14 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1' }]; - const request = spec.buildRequests(bidRequestsWithPubcid); + const request = spec.buildRequests(bidRequestsWithPubcid, mockBidderRequest); expect(request[0].data.pubcid).to.equal('c1a4c843-2368-4b5e-b3b1-6ee4702b9ad6'); }); }); describe('with the trade desk unified id', function () { it('should not send a tdid query param when there is no userId.tdid defined in the bid requests', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].data).to.not.have.any.keys('ttduuid'); }); @@ -1130,14 +1069,14 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1' }]; - const request = spec.buildRequests(bidRequestsWithTdid); + const request = spec.buildRequests(bidRequestsWithTdid, mockBidderRequest); expect(request[0].data.ttduuid).to.equal('00000000-aaaa-1111-bbbb-222222222222'); }); }); describe('with the liveRamp identity link envelope', function () { it('should not send a tdid query param when there is no userId.lre defined in the bid requests', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].data).to.not.have.any.keys('lre'); }); @@ -1161,7 +1100,7 @@ describe('OpenxAdapter', function () { bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1' }]; - const request = spec.buildRequests(bidRequestsWithLiveRampEnvelope); + const request = spec.buildRequests(bidRequestsWithLiveRampEnvelope, mockBidderRequest); expect(request[0].data.lre).to.equal('00000000-aaaa-1111-bbbb-222222222222'); }); }); @@ -1187,36 +1126,15 @@ describe('OpenxAdapter', function () { 'auctionId': '1d1a030790a475', 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }]; - - const bidRequestsWithMediaType = [{ - 'bidder': 'openx', - 'mediaType': 'video', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [640, 480], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' - }]; - - it('should send bid request to openx url via GET, with mediaType as video', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); - expect(request[0].url).to.equal('https://' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); - expect(request[0].method).to.equal('GET'); - }); + const mockBidderRequest = {refererInfo: {}}; it('should send bid request to openx url via GET, with mediaTypes having video parameter', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].url).to.equal('https://' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); - it('should have the correct parameters', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); const dataParams = request[0].data; expect(dataParams.auid).to.equal('12345678'); @@ -1225,7 +1143,7 @@ describe('OpenxAdapter', function () { }); it('should send a bc parameter', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes); + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); const dataParams = request[0].data; expect(dataParams.bc).to.have.string('hb_pb'); @@ -1233,6 +1151,7 @@ describe('OpenxAdapter', function () { describe('when using the video param', function () { let videoBidRequest; + let mockBidderRequest = {refererInfo: {}}; beforeEach(function () { videoBidRequest = { @@ -1253,13 +1172,14 @@ describe('OpenxAdapter', function () { 'auctionId': '1d1a030790a475', 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' } + mockBidderRequest = {refererInfo: {}}; }); it('should not allow you to set a url', function () { videoBidRequest.params.video = { url: 'test-url' }; - const request = spec.buildRequests([videoBidRequest]); + const request = spec.buildRequests([videoBidRequest], mockBidderRequest); expect(request[0].data.url).to.be.undefined; }); @@ -1269,7 +1189,7 @@ describe('OpenxAdapter', function () { videoBidRequest.params.video = { ju: myUrl }; - const request = spec.buildRequests([videoBidRequest]); + const request = spec.buildRequests([videoBidRequest], mockBidderRequest); expect(request[0].data.ju).to.not.equal(myUrl); }); @@ -1280,7 +1200,7 @@ describe('OpenxAdapter', function () { videoBidRequest.params.video = { openrtb: myOpenRTBObject }; - const request = spec.buildRequests([videoBidRequest]); + const request = spec.buildRequests([videoBidRequest], mockBidderRequest); expect(request[0].data.openrtb).to.equal(JSON.stringify(myOpenRTBObject)); }); @@ -1292,7 +1212,7 @@ describe('OpenxAdapter', function () { videoBidRequest.params.video = { openrtb: myOpenRTBObject }; - const request = spec.buildRequests([videoBidRequest]); + const request = spec.buildRequests([videoBidRequest], mockBidderRequest); const openRtbRequestParams = JSON.parse(request[0].data.openrtb); expect(openRtbRequestParams.w).to.not.equal(width); @@ -1308,7 +1228,7 @@ describe('OpenxAdapter', function () { }; videoBidRequest.mediaTypes.video.playerSize = undefined; - const request = spec.buildRequests([videoBidRequest]); + const request = spec.buildRequests([videoBidRequest], mockBidderRequest); const openRtbRequestParams = JSON.parse(request[0].data.openrtb); expect(openRtbRequestParams.w).to.equal(width); @@ -1339,10 +1259,13 @@ describe('OpenxAdapter', function () { auctionId: '1d1a030790a475', transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' }; + let mockBidderRequest = {refererInfo: {}}; + + it('should default to a banner request', function () { + const request = spec.buildRequests([multiformatBid], mockBidderRequest); + const dataParams = request[0].data; - it('should send bid request to openx url via GET, with mediaType specified as banner', function () { - const request = spec.buildRequests([multiformatBid]); - expect(request[0].url).to.equal(`https://${multiformatBid.params.delDomain}${URLBASE}`); + expect(dataParams.divIds).to.have.string(multiformatBid.adUnitCode); }); }); @@ -1450,12 +1373,6 @@ describe('OpenxAdapter', function () { it('should return a brand ID', function () { expect(bid.meta.dspid).to.equal(DEFAULT_TEST_ARJ_AD_UNIT.adv_id); }); - - it('should register a beacon', function () { - resetBoPixel(); - spec.interpretResponse({body: bidResponse}, bidRequest); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`https:\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); - }); }); describe('when there is a deal', function () { @@ -1745,14 +1662,6 @@ describe('OpenxAdapter', function () { const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaType); expect(result.length).to.equal(0); }); - - it('should register a beacon', function () { - resetBoPixel(); - spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^https:\/\/test-colo\.com/)); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ph=test-ph/)); - sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/ts=test-ts/)); - }); }); describe('user sync', function () { diff --git a/test/spec/modules/openxoutstreamBidAdapter_spec.js b/test/spec/modules/openxoutstreamBidAdapter_spec.js index 634df1c8c6a..9d2b7082a22 100644 --- a/test/spec/modules/openxoutstreamBidAdapter_spec.js +++ b/test/spec/modules/openxoutstreamBidAdapter_spec.js @@ -13,12 +13,6 @@ describe('OpenXOutstreamAdapter', function () { const CR_ID = '2052941939925262540'; const AD_ID = '1991358644725162800'; - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - describe('isBidRequestValid', function () { describe('when request is for a banner ad', function () { let bannerBid; @@ -80,8 +74,10 @@ describe('OpenXOutstreamAdapter', function () { 'auctionId': '1d1a030790a475' }]; + const mockBidderRequest = {refererInfo: {}}; + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { - const request = spec.buildRequests(bidRequestsWithMediaType); + const request = spec.buildRequests(bidRequestsWithMediaType, mockBidderRequest); const params = bidRequestsWithMediaType[0].params; expect(request[0].url).to.equal(`https://` + params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); @@ -97,7 +93,6 @@ describe('OpenXOutstreamAdapter', function () { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - sizes: [300, 250], mediaTypes: { banner: { sizes: [[728, 90]] @@ -112,7 +107,6 @@ describe('OpenXOutstreamAdapter', function () { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - 'sizes': [300, 250], mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] @@ -122,7 +116,7 @@ describe('OpenXOutstreamAdapter', function () { 'bidderRequestId': 'test-bid-request-1', 'auctionId': 'test-auction-1' }]; - const request = spec.buildRequests(bidRequestsWithUnitIds); + const request = spec.buildRequests(bidRequestsWithUnitIds, mockBidderRequest); expect(request[0].data.auid).to.equal(`${bidRequestsWithUnitIds[0].params.unit}`); expect(request[0].data.vht).to.not.equal(`${bidRequestsWithUnitIds[0].params.height}`); expect(request[0].data.vwd).to.not.equal(`${bidRequestsWithUnitIds[0].params.width}`); From 16fc70727a40e198749ab873457ea5a7ddaa55c4 Mon Sep 17 00:00:00 2001 From: susyt Date: Thu, 7 Nov 2019 12:14:56 -0800 Subject: [PATCH 380/436] GumGum: use mediaTypes.banner.sizes (#4416) * adds digitrust module, mods gdpr from bool to int * update unit test * only send gdprconsent if present * uses mediaTypes before trying bidRequest sizes * removes use of deprecated method --- modules/gumgumBidAdapter.js | 5 +++-- test/spec/modules/gumgumBidAdapter_spec.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 60f446b12ee..585d3279a07 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -41,7 +41,7 @@ function _getBrowserParams(topWindowUrl) { try { topWindow = global.top; topScreen = topWindow.screen; - topUrl = topWindowUrl || utils.getTopWindowUrl(); + topUrl = topWindowUrl || ''; } catch (error) { utils.logError(error); return browserParams @@ -145,6 +145,7 @@ function buildRequests (validBidRequests, bidderRequest) { userId = {} } = bidRequest; const data = {}; + const sizes = bidRequest.mediaTypes && bidRequest.mediaTypes.banner && bidRequest.mediaTypes.banner.sizes; const topWindowUrl = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; if (pageViewId) { data.pv = pageViewId @@ -177,7 +178,7 @@ function buildRequests (validBidRequests, bidderRequest) { tId: transactionId, pi: data.pi, selector: params.selector, - sizes: bidRequest.sizes || bidRequest.mediatype[banner].sizes, + sizes: sizes || bidRequest.sizes, url: BID_ENDPOINT, method: 'GET', data: Object.assign(data, _getBrowserParams(topWindowUrl), _getDigiTrustQueryParams(userId), _getTradeDeskIDParam(userId)) diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 82c8e494533..0d00eb2b93c 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -21,7 +21,11 @@ describe('gumgumAdapter', function () { 'bidfloor': 0.05 }, 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600], [1, 1]], + 'mediaTypes': { + 'banner': { + sizes: [[300, 250], [300, 600], [1, 1]] + } + }, 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', From 065839d9e26f11aa1b79e8542fb6508f06ac26f4 Mon Sep 17 00:00:00 2001 From: Marcian123 Date: Thu, 7 Nov 2019 21:28:08 +0100 Subject: [PATCH 381/436] RTBhouse Bid Adapter update for 3.0 (#4428) --- modules/rtbhouseBidAdapter.js | 7 ++++--- modules/rtbhouseBidAdapter.md | 6 +++++- test/spec/modules/rtbhouseBidAdapter_spec.js | 19 +++++++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index 245fc5f3ea2..36c08fc8626 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -115,10 +115,11 @@ function mapBanner(slot) { if (slot.mediaType === 'banner' || utils.deepAccess(slot, 'mediaTypes.banner') || (!slot.mediaType && !slot.mediaTypes)) { + var sizes = slot.sizes || slot.mediaTypes.banner.sizes; return { - w: slot.sizes[0][0], - h: slot.sizes[0][1], - format: slot.sizes.map(size => ({ + w: sizes[0][0], + h: sizes[0][1], + format: sizes.map(size => ({ w: size[0], h: size[1] })) diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md index 233ed34053a..b8b59aa9edc 100644 --- a/modules/rtbhouseBidAdapter.md +++ b/modules/rtbhouseBidAdapter.md @@ -17,7 +17,11 @@ Please reach out to pmp@rtbhouse.com to receive your own // banner { code: 'test-div', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, bids: [ { bidder: "rtbhouse", diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index 707a5f91bec..67845fa1983 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -19,7 +19,11 @@ describe('RTBHouseAdapter', () => { 'region': 'prebid-eu' }, 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]], + } + }, 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' @@ -29,6 +33,13 @@ describe('RTBHouseAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); + it('Checking backward compatibility. should return true', function () { + let bid2 = Object.assign({}, bid); + delete bid2.mediaTypes; + bid2.sizes = [[300, 250], [300, 600]]; + expect(spec.isBidRequestValid(bid2)).to.equal(true); + }); + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; @@ -49,7 +60,11 @@ describe('RTBHouseAdapter', () => { 'test': 1 }, 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]], + } + }, 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', From bf94a0d9ee59b99c577b6a9b17e713a6a11041b5 Mon Sep 17 00:00:00 2001 From: koji-eguchi <50477903+koji-eguchi@users.noreply.github.com> Date: Fri, 8 Nov 2019 05:30:24 +0900 Subject: [PATCH 382/436] add viewable rendering format (#4201) --- modules/yieldoneBidAdapter.js | 50 ++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index c706a6e7d45..9920c93696e 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -8,6 +8,7 @@ const BIDDER_CODE = 'yieldone'; const ENDPOINT_URL = 'https://y.one.impact-ad.jp/h_bid'; const USER_SYNC_URL = 'https://y.one.impact-ad.jp/push_sync'; const VIDEO_PLAYER_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; +const VIEWABLE_PERCENTAGE_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/prebid-adformat-config.js'; export const spec = { code: BIDDER_CODE, @@ -64,6 +65,7 @@ export const spec = { const cpm = response.cpm * 1000 || 0; if (width !== 0 && height !== 0 && cpm !== 0 && crid !== 0) { const dealId = response.dealId || ''; + const renderId = response.renderid || ''; const currency = response.currency || 'JPY'; const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; const referrer = utils.getTopWindowUrl(); @@ -80,7 +82,53 @@ export const spec = { referrer: referrer }; - if (response.adTag) { + if (response.adTag && renderId === 'ViewableRendering') { + bidResponse.mediaType = BANNER; + let viewableScript = ` + + + `; + bidResponse.ad = viewableScript; + } else if (response.adTag) { bidResponse.mediaType = BANNER; bidResponse.ad = response.adTag; } else if (response.adm) { From bb4ae80656de6481f29e42d5b8053818906f360b Mon Sep 17 00:00:00 2001 From: sourabhg Date: Fri, 8 Nov 2019 14:27:12 +0530 Subject: [PATCH 383/436] Feature/adapter (#4219) * feat(bidrequest): code for making bidrequest * feat(bidresponse): format and return the response * feat(tests): added tests for adapter * feat(docs): added docs for the adapter * refactor(url): changed adserver url * test(user sync): added unit tests for the user syncs * refactor(endpoint): changed endpoint for prebid * refactor(endpoint): changed endpoint for prebid * doc(tagid): mandatory param definition added * fix(imp id): fix for correct impression id * fix(width/height): fix for correct width and height sequence --- modules/deepintentBidAdapter.js | 142 +++++++++++++++ modules/deepintentBidAdapter.md | 53 ++++++ .../spec/modules/deepintentBidAdapter_spec.js | 162 ++++++++++++++++++ 3 files changed, 357 insertions(+) create mode 100644 modules/deepintentBidAdapter.js create mode 100644 modules/deepintentBidAdapter.md create mode 100644 test/spec/modules/deepintentBidAdapter_spec.js diff --git a/modules/deepintentBidAdapter.js b/modules/deepintentBidAdapter.js new file mode 100644 index 00000000000..27aa4e2c8a6 --- /dev/null +++ b/modules/deepintentBidAdapter.js @@ -0,0 +1,142 @@ +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER} from '../src/mediaTypes'; +import * as utils from '../src/utils'; +const BIDDER_CODE = 'deepintent'; +const BIDDER_ENDPOINT = 'https://prebid.deepintent.com/prebid'; +const USER_SYNC_URL = 'https://beacon.deepintent.com/usersync.html'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + aliases: [], + + // tagId is mandatory param + isBidRequestValid: bid => { + let valid = false; + if (bid && bid.params && bid.params.tagId) { + if (typeof bid.params.tagId === 'string' || bid.params.tagId instanceof String) { + valid = true; + } + } + return valid; + }, + interpretResponse: function(bidResponse, request) { + let responses = []; + if (bidResponse && bidResponse.body) { + let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : []; + responses = bids.map(bid => formatResponse(bid)) + } + return responses; + }, + buildRequests: function (validBidRequests, bidderRequest) { + const openRtbBidRequest = { + id: utils.generateUUID(), + at: 1, + imp: validBidRequests.map(bid => buildImpression(bid)), + site: buildSite(bidderRequest), + device: buildDevice(), + source: { + fd: 0, + ext: { + type: 2 + } + } + }; + + return { + method: 'POST', + url: BIDDER_ENDPOINT, + data: JSON.stringify(openRtbBidRequest), + options: { + contentType: 'application/json' + } + }; + }, + /** + * Register User Sync. + */ + getUserSyncs: syncOptions => { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USER_SYNC_URL + }]; + } + } + +}; + +function formatResponse(bid) { + return { + requestId: bid && bid.impid ? bid.impid : undefined, + cpm: bid && bid.price ? bid.price : 0.0, + width: bid && bid.w ? bid.w : 0, + height: bid && bid.h ? bid.h : 0, + ad: bid && bid.adm ? bid.adm : '', + creativeId: bid && bid.crid ? bid.crid : undefined, + netRevenue: false, + currency: bid && bid.cur ? bid.cur : 'USD', + ttl: 300, + dealId: bid && bid.dealId ? bid.dealId : undefined + } +} + +function buildImpression(bid) { + return { + id: bid.bidId, + tagid: bid.params.tagId || '', + secure: window.location.protocol === 'https' ? 1 : 0, + banner: buildBanner(bid), + ext: bid.params.custom ? bid.params.custom : {} + }; +} + +function buildBanner(bid) { + if (utils.deepAccess(bid, 'mediaTypes.banner')) { + // Get Sizes from MediaTypes Object, Will always take first size, will be overrided by params for exact w,h + if (utils.deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.height && !bid.params.width) { + let sizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes'); + if (utils.isArray(sizes) && sizes.length > 0) { + return { + h: sizes[0][1], + w: sizes[0][0] + } + } + } else { + return { + h: bid.params.height, + w: bid.params.width + } + } + } +} + +function buildSite(bidderRequest) { + let site = {}; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + site.page = bidderRequest.refererInfo.referer; + site.domain = getDomain(bidderRequest.refererInfo.referer); + } + return site; +} + +function getDomain(referer) { + if (referer) { + let domainA = document.createElement('a'); + domainA.href = referer; + return domainA.hostname; + } +} + +function buildDevice() { + return { + ua: navigator.userAgent, + js: 1, + dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack === '1') ? 1 : 0, + h: screen.height, + w: screen.width, + language: navigator.language + } +} + +registerBidder(spec); diff --git a/modules/deepintentBidAdapter.md b/modules/deepintentBidAdapter.md new file mode 100644 index 00000000000..7f5afbd233a --- /dev/null +++ b/modules/deepintentBidAdapter.md @@ -0,0 +1,53 @@ +# Overview + +``` +Module Name: Deepintent Bidder Adapter +Module Type: Bidder Adapter +Maintainer: prebid@deepintent.com +``` + +# Description + +Deepintent currently supports the BANNER type ads through prebid js + +Module that connects to Deepintent's demand sources. + +# Banner Test Request +``` + var adUnits = [ + { + code: 'di_adUnit1', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size, only first one will be picked up since multiple ad sizes are not supported yet + } + } + bids: [ + { + bidder: 'deepintent', + params: { + tagId: '1300', // Required parameter + w: 300, // Width and Height here will override sizes in mediatype + h: 250, + custom: { // Custom parameters in form of key value pairs + user_min_age: 18 + } + } + } + ] + } + ]; +``` + +###Recommended User Sync Configuration + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['deepintent'], + syncDelay: 3000 + }}); + + +``` diff --git a/test/spec/modules/deepintentBidAdapter_spec.js b/test/spec/modules/deepintentBidAdapter_spec.js new file mode 100644 index 00000000000..353a815eb8c --- /dev/null +++ b/test/spec/modules/deepintentBidAdapter_spec.js @@ -0,0 +1,162 @@ +import {expect} from 'chai'; +import {spec} from 'modules/deepintentBidAdapter'; +import * as utils from '../../../src/utils'; + +describe('Deepintent adapter', function () { + let request; + let bannerResponse; + + beforeEach(function () { + request = [ + { + bidder: 'deepintent', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + params: { + tagId: '100013', + w: 728, + h: 90, + custom: { + user_gender: 'female', + user_max_age: 25 + } + } + } + ]; + bannerResponse = { + 'body': { + 'id': '303e1fae-9677-41e2-9a92-15a23445363f', + 'seatbid': [{ + 'bid': [{ + 'id': '11447bb1-a266-470d-b0d7-8810f5b1b75f', + 'impid': 'a7e92b9b-d9db-4de8-9c3f-f90737335445', + 'price': 0.6, + 'adid': '10001', + 'adm': "\r\n", + 'adomain': ['deepintent.com'], + 'cid': '103389', + 'crid': '13665', + 'w': 300, + 'h': 250, + 'dealId': 'dee_12312stdszzsx' + }], + 'seat': '10000' + }], + 'bidid': '0b08b09f-aaa1-4c14-b1c8-7debb1a7c1cd' + } + } + }); + + describe('validations', function () { + it('validBid : tagId is passed', function () { + let bid = { + bidder: 'deepintent', + params: { + tagId: '1232' + } + }, + isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equals(true); + }); + it('invalidBid : tagId is not passed', function () { + let bid = { + bidder: 'deepintent', + params: { + h: 200, + w: 300 + } + }, + isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equals(false); + }); + it('invalidBid : tagId is not a string', function () { + let bid = { + bidder: 'deepintent', + params: { + tagId: 12345 + } + }, + isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equals(false); + }); + }); + describe('request check', function () { + it('unmutaable bid request check', function () { + let oRequest = utils.deepClone(request), + bidRequest = spec.buildRequests(request); + expect(request).to.deep.equal(oRequest); + }); + it('bidder connection check', function () { + let bRequest = spec.buildRequests(request); + expect(bRequest.url).to.equal('https://prebid.deepintent.com/prebid'); + expect(bRequest.method).to.equal('POST'); + expect(bRequest.options.contentType).to.equal('application/json'); + }); + it('bid request check : Device', function () { + let bRequest = spec.buildRequests(request); + let data = JSON.parse(bRequest.data); + expect(data.device.ua).to.be.a('string'); + expect(data.device.js).to.equal(1); + expect(data.device.dnt).to.be.a('number'); + expect(data.device.h).to.be.a('number'); + expect(data.device.w).to.be.a('number'); + }); + it('bid request check : Impression', function () { + let bRequest = spec.buildRequests(request); + let data = JSON.parse(bRequest.data); + expect(data.at).to.equal(1); // auction type + expect(data.imp[0].id).to.equal(request[0].bidId); + expect(data.imp[0].tagid).to.equal('100013'); + }); + it('bid request check : ad size', function () { + let bRequest = spec.buildRequests(request); + let data = JSON.parse(bRequest.data); + expect(data.imp[0].banner).to.be.a('object'); + expect(data.imp[0].banner.w).to.equal(300); + expect(data.imp[0].banner.h).to.equal(250); + }); + it('bid request check : custom params', function () { + let bRequest = spec.buildRequests(request); + let data = JSON.parse(bRequest.data); + expect(data.imp[0].ext).to.be.a('object'); + expect(data.imp[0].ext.user_gender).to.equal('female'); + expect(data.imp[0].ext.user_max_age).to.equal(25); + }); + it('bid request check: source params', function () { + let bRequest = spec.buildRequests(request); + let data = JSON.parse(bRequest.data); + expect(data.source.fd).to.equal(0); + expect(data.source.ext.type).to.equal(2); + }) + }); + describe('user sync check', function () { + it('user sync url check', function () { + let syncOptions = { + iframeEnabled: true + }; + let userSync = spec.getUserSyncs(syncOptions); + expect(userSync).to.be.an('array').with.length.above(0); + expect(userSync[0].type).to.equal('iframe'); + expect(userSync[0].url).to.equal('https://beacon.deepintent.com/usersync.html'); + }); + }); + describe('response check', function () { + it('bid response check: valid bid response', function () { + let bRequest = spec.buildRequests(request); + let data = JSON.parse(bRequest.data); + let bResponse = spec.interpretResponse(bannerResponse, request); + expect(bResponse).to.be.an('array').with.length.above(0); + expect(bResponse[0].requestId).to.equal(bannerResponse.body.seatbid[0].bid[0].impid); + expect(bResponse[0].width).to.equal(bannerResponse.body.seatbid[0].bid[0].w); + expect(bResponse[0].height).to.equal(bannerResponse.body.seatbid[0].bid[0].h); + expect(bResponse[0].currency).to.equal('USD'); + expect(bResponse[0].netRevenue).to.equal(false); + expect(bResponse[0].ttl).to.equal(300); + expect(bResponse[0].creativeId).to.equal(bannerResponse.body.seatbid[0].bid[0].crid); + expect(bResponse[0].dealId).to.equal(bannerResponse.body.seatbid[0].bid[0].dealId); + }); + }) +}); From 95dbc492ea3ee6f7f8a33fb62a70f76e13a85532 Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Fri, 8 Nov 2019 09:58:11 -0500 Subject: [PATCH 384/436] PulsePoint Bid Adapter: Support for schain (#4433) * 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 * ET-5938 SupplyChain Object Support * Formatting * Code review * Code review * Fix to currency parsing on response --- modules/pulsepointBidAdapter.js | 15 ++++- .../spec/modules/pulsepointBidAdapter_spec.js | 56 +++++++++++++++++-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 3cdbd559614..c3fd1fa5eaf 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -47,6 +47,7 @@ export const spec = { badv: bidRequests[0].params.badv, user: user(bidRequests[0], bidderRequest), regs: regs(bidderRequest), + source: source(bidRequests[0].schain), }; return { method: 'POST', @@ -116,7 +117,7 @@ function bidResponseAvailable(request, response) { adId: id, ttl: idToBidMap[id].exp || DEFAULT_BID_TTL, netRevenue: DEFAULT_NET_REVENUE, - currency: idToBidMap[id].cur || DEFAULT_CURRENCY + currency: bidResponse.cur || DEFAULT_CURRENCY }; if (idToImpMap[id]['native']) { bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); @@ -428,6 +429,18 @@ function regs(bidderRequest) { return null; } +/** + * Creates source object with supply chain + */ +function source(schain) { + if (schain) { + return { + ext: { schain } + }; + } + return null; +} + /** * 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 6d5400de216..b62b799c8a0 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -138,6 +138,35 @@ describe('PulsePoint Adapter Tests', function () { } } }]; + + const schainParamsSlotConfig = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '1x1', + bcat: ['IAB-1', 'IAB-20'], + battr: [1, 2, 3], + bidfloor: 1.5, + badv: ['cocacola.com', 'lays.com'] + }, + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + } + ] + }, + }]; + const bidderRequest = { refererInfo: { referer: 'https://publisher.com/home' @@ -210,15 +239,15 @@ describe('PulsePoint Adapter Tests', function () { price: 1.25, adm: 'This is an Ad#1', crid: 'Creative#123', - exp: 50, - cur: 'GBP' + exp: 50 }, { impid: ortbRequest.imp[1].id, price: 1.25, adm: 'This is an Ad#2', crid: 'Creative#123' }] - }] + }], + cur: 'GBP' }; const bids = spec.interpretResponse({ body: ortbResponse }, request); expect(bids).to.have.lengthOf(2); @@ -232,7 +261,7 @@ describe('PulsePoint Adapter Tests', function () { expect(secondBid.cpm).to.equal(1.25); expect(secondBid.ad).to.equal('This is an Ad#2'); expect(secondBid.ttl).to.equal(20); - expect(secondBid.currency).to.equal('USD'); + expect(secondBid.currency).to.equal('GBP'); }); it('Verify full passback', function () { @@ -485,6 +514,25 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.imp[1].ext).to.be.null; }); + it('Verify schain parameters', function () { + const request = spec.buildRequests(schainParamsSlotConfig, bidderRequest); + const ortbRequest = request.data; + expect(ortbRequest).to.not.equal(null); + expect(ortbRequest.source).to.not.equal(null); + expect(ortbRequest.source.ext).to.not.equal(null); + expect(ortbRequest.source.ext.schain).to.not.equal(null); + expect(ortbRequest.source.ext.schain.complete).to.equal(1); + expect(ortbRequest.source.ext.schain.ver).to.equal('1.0'); + expect(ortbRequest.source.ext.schain.nodes).to.not.equal(null); + expect(ortbRequest.source.ext.schain.nodes).to.lengthOf(1); + expect(ortbRequest.source.ext.schain.nodes[0].asi).to.equal('exchange1.com'); + expect(ortbRequest.source.ext.schain.nodes[0].sid).to.equal('1234'); + expect(ortbRequest.source.ext.schain.nodes[0].hp).to.equal(1); + expect(ortbRequest.source.ext.schain.nodes[0].rid).to.equal('bid-request-1'); + expect(ortbRequest.source.ext.schain.nodes[0].name).to.equal('publisher'); + expect(ortbRequest.source.ext.schain.nodes[0].domain).to.equal('publisher.com'); + }); + it('Verify outstream renderer', function () { const bidderRequestOutstream = Object.assign({}, bidderRequest, {bids: [outstreamSlotConfig[0]]}); const request = spec.buildRequests(outstreamSlotConfig, bidderRequestOutstream); From a3e3aa97eb23ca2fb3a1624932035b4ee126261e Mon Sep 17 00:00:00 2001 From: Alexis Andrieu Date: Fri, 8 Nov 2019 16:49:57 +0100 Subject: [PATCH 385/436] Add supply chain support for Teads adapter (#4420) --- modules/teadsBidAdapter.js | 4 ++++ test/spec/modules/teadsBidAdapter_spec.js | 28 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index 121232a6605..856df879270 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -46,6 +46,10 @@ export const spec = { hb_version: '$prebid.version$' }; + if (validBidRequests[0].schain) { + payload.schain = validBidRequests[0].schain; + } + let gdpr = bidderRequest.gdprConsent; if (bidderRequest && gdpr) { let isCmp = (typeof gdpr.gdprApplies === 'boolean') diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index af1c7a9c01b..5d92f9d7a08 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -226,6 +226,34 @@ describe('teadsBidAdapter', () => { checkMediaTypesSizes(mediaTypesPlayerSize, '32x34') }); + it('should add schain info to payload if available', function () { + const bidRequest = Object.assign({}, bidRequests[0], { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ + asi: 'example.com', + sid: '00001', + hp: 1 + }] + } + }); + + const request = spec.buildRequests([bidRequest], bidderResquestDefault); + const payload = JSON.parse(request.data); + + expect(payload.schain).to.exist; + expect(payload.schain).to.deep.equal({ + ver: '1.0', + complete: 1, + nodes: [{ + asi: 'example.com', + sid: '00001', + hp: 1 + }] + }); + }); + it('should use good mediaTypes video sizes', function() { const mediaTypesVideoSizes = { 'mediaTypes': { From 0b035055811793017220359ff6a101eb14367190 Mon Sep 17 00:00:00 2001 From: TJ Eastmond Date: Fri, 8 Nov 2019 14:03:17 -0500 Subject: [PATCH 386/436] Rubicon: support SupplyChain (schain) (#4315) * Add microadBidAdapter * Remove unnecessary encodeURIComponent from microadBidAdapter * Submit Advangelists Prebid Adapter * Submit Advangelists Prebid Adapter 1.1 * Correct procudtion endpoint for prebid * analytics update with wrapper name * reverted error merge * update changed default value of netRevenue to true * Starting schain * More tests for banner schain support * Video tests * Encoding tweaks, required fields and comments * Removed .only() from tests * Change requests per Bret --- modules/rubiconBidAdapter.js | 68 +++++++++- test/spec/modules/rubiconBidAdapter_spec.js | 137 ++++++++++++++++++++ 2 files changed, 203 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 998f4826ead..fddf70229af 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -260,6 +260,10 @@ export const spec = { utils.deepSetValue(data, 'regs.coppa', 1); } + if (bidRequest.schain && hasValidSupplyChainParams(bidRequest.schain)) { + utils.deepSetValue(data, 'source.ext.schain', bidRequest.schain); + } + return { method: 'POST', url: VIDEO_ENDPOINT, @@ -277,7 +281,7 @@ export const spec = { url: FASTLANE_ENDPOINT, data: spec.getOrderedParams(bidParams).reduce((paramString, key) => { const propValue = bidParams[key]; - return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${encodeParam(key, propValue)}&` : paramString; }, '') + `slots=1&rand=${Math.random()}`, bidRequest }; @@ -308,7 +312,7 @@ export const spec = { url: FASTLANE_ENDPOINT, data: spec.getOrderedParams(combinedSlotParams).reduce((paramString, key) => { const propValue = combinedSlotParams[key]; - return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${key}=${encodeURIComponent(propValue)}&` : paramString; + return ((utils.isStr(propValue) && propValue !== '') || utils.isNumber(propValue)) ? `${paramString}${encodeParam(key, propValue)}&` : paramString; }, '') + `slots=${bidsInGroup.length}&rand=${Math.random()}`, bidRequest: bidsInGroup }); @@ -332,6 +336,8 @@ export const spec = { 'p_pos', 'gdpr', 'gdpr_consent', + 'rp_schain', + 'rf', 'tpid_tdid', 'tpid_liveintent.com', 'tg_v.LIseg', @@ -482,9 +488,38 @@ export const spec = { data['coppa'] = 1; } + // if SupplyChain is supplied and contains all required fields + if (bidRequest.schain && hasValidSupplyChainParams(bidRequest.schain)) { + data.rp_schain = spec.serializeSupplyChain(bidRequest.schain); + } + return data; }, + /** + * Serializes schain params according to OpenRTB requirements + * @param {Object} supplyChain + * @returns {String} + */ + serializeSupplyChain: function (supplyChain) { + const supplyChainIsValid = hasValidSupplyChainParams(supplyChain); + if (!supplyChainIsValid) return ''; + const { ver, complete, nodes } = supplyChain; + return `${ver},${complete}!${spec.serializeSupplyChainNodes(nodes)}`; + }, + + /** + * Properly sorts schain object params + * @param {Array} nodes + * @returns {String} + */ + serializeSupplyChainNodes: function (nodes) { + const nodePropOrder = ['asi', 'sid', 'hp', 'rid', 'name', 'domain']; + return nodes.map(node => { + return nodePropOrder.map(prop => encodeURIComponent(node[prop] || '')).join(','); + }).join('!'); + }, + /** * @param {*} responseObj * @param {BidRequest|Object.} bidRequest - if request was SRA the bidRequest argument will be a keyed BidRequest array object, @@ -982,6 +1017,35 @@ export function hasValidVideoParams(bid) { return isValid; } +/** + * Make sure the required params are present + * @param {Object} schain + * @param {Bool} + */ +export function hasValidSupplyChainParams(schain) { + let isValid = false; + const requiredFields = ['asi', 'sid', 'hp']; + if (!schain.nodes) return isValid; + isValid = schain.nodes.reduce((status, node) => { + if (!status) return status; + return requiredFields.every(field => node[field]); + }, true); + if (!isValid) utils.logError('Rubicon: required schain params missing'); + return isValid; +} + +/** + * Creates a URL key value param, encoding the + * param unless the key is schain + * @param {String} key + * @param {String} param + * @returns {String} + */ +export function encodeParam(key, param) { + if (key === 'rp_schain') return `rp_schain=${param}`; + return `${key}=${encodeURIComponent(param)}`; +} + /** * split array into multiple arrays of defined size * @param {Array} array diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index e037c7d5ed7..64c0f450e39 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -68,6 +68,49 @@ describe('the rubicon adapter', function () { * @param {Array.} [indexOverMap] * @return {{status: string, cpm: number, zone_id: *, size_id: *, impression_id: *, ad_id: *, creative_id: string, type: string, targeting: *[]}} */ + + function getBidderRequest() { + return { + bidderCode: 'rubicon', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + bidderRequestId: '178e34bad3658f', + bids: [ + { + bidder: 'rubicon', + params: { + accountId: '14062', + siteId: '70608', + zoneId: '335918', + userId: '12346', + keywords: ['a', 'b', 'c'], + inventory: { + rating: '5-star', // This actually should not be sent to frank!! causes 400 + prodtype: ['tech', 'mobile'] + }, + visitor: { + ucat: 'new', + lastsearch: 'iphone', + likes: ['sports', 'video games'] + }, + position: 'atf', + referrer: 'localhost', + latLong: [40.7607823, '111.8910325'] + }, + adUnitCode: '/19968336/header-bid-tag-0', + code: 'div-1', + sizes: [[300, 250], [320, 50]], + bidId: '2ffb201a808da7', + bidderRequestId: '178e34bad3658f', + auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' + } + ], + start: 1472239426002, + auctionStart: 1472239426000, + timeout: 5000 + }; + }; + function createResponseAdByIndex(i, sizeId, indexOverMap) { const overridePropMap = (indexOverMap && indexOverMap[i] && typeof indexOverMap[i] === 'object') ? indexOverMap[i] : {}; const overrideProps = Object.keys(overridePropMap).reduce((aggregate, key) => { @@ -2267,4 +2310,98 @@ describe('the rubicon adapter', function () { }); }); }); + + describe.only('Supply Chain Support', function() { + const nodePropsOrder = ['asi', 'sid', 'hp', 'rid', 'name', 'domain']; + let bidRequests; + let schainConfig; + + const getSupplyChainConfig = () => { + return { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'rubicon.com', + sid: '1234', + hp: 1, + rid: 'bid-request-1', + name: 'pub one', + domain: 'pub1.com' + }, + { + asi: 'theexchange.com', + sid: '5678', + hp: 1, + rid: 'bid-request-2', + name: 'pub two', + domain: 'pub2.com' + }, + { + asi: 'wesellads.com', + sid: '9876', + hp: 1, + rid: 'bid-request-3', + // name: 'alladsallthetime', + domain: 'alladsallthetime.com' + } + ] + }; + }; + + beforeEach(() => { + bidRequests = getBidderRequest(); + schainConfig = getSupplyChainConfig(); + bidRequests.bids[0].schain = schainConfig; + }); + + it('should properly serialize schain object with correct delimiters', () => { + const results = spec.buildRequests(bidRequests.bids, bidRequests); + const numNodes = schainConfig.nodes.length; + const schain = parseQuery(results[0].data).rp_schain; + + // each node serialization should start with an ! + expect(schain.match(/!/g).length).to.equal(numNodes); + + // 5 commas per node plus 1 for version + expect(schain.match(/,/g).length).to.equal(numNodes * 5 + 1); + }); + + it('should send the proper version for the schain', () => { + const results = spec.buildRequests(bidRequests.bids, bidRequests); + const schain = parseQuery(results[0].data).rp_schain.split('!'); + const version = schain.shift().split(',')[0]; + expect(version).to.equal(bidRequests.bids[0].schain.ver); + }); + + it('should send the correct value for complete in schain', () => { + const results = spec.buildRequests(bidRequests.bids, bidRequests); + const schain = parseQuery(results[0].data).rp_schain.split('!'); + const complete = schain.shift().split(',')[1]; + expect(complete).to.equal(String(bidRequests.bids[0].schain.complete)); + }); + + it('should send available params in the right order', () => { + const results = spec.buildRequests(bidRequests.bids, bidRequests); + const schain = parseQuery(results[0].data).rp_schain.split('!'); + schain.shift(); + + schain.forEach((serializeNode, nodeIndex) => { + const nodeProps = serializeNode.split(','); + nodeProps.forEach((nodeProp, propIndex) => { + const node = schainConfig.nodes[nodeIndex]; + const key = nodePropsOrder[propIndex]; + expect(nodeProp).to.equal(node[key] ? String(node[key]) : ''); + }); + }); + }); + + it('should copy the schain JSON to to bid.source.ext.schain', () => { + createVideoBidderRequest(); + const schain = getSupplyChainConfig(); + bidderRequest.bids[0].schain = schain; + const request = spec.buildRequests(bidderRequest.bids, bidderRequest); + expect(request[0].data.source.ext.schain).to.deep.equal(schain); + }); + }); }); From 37cc90a92602d4c981ea389b3a55d5b935001671 Mon Sep 17 00:00:00 2001 From: Vlad Gurgov Date: Sun, 10 Nov 2019 23:26:28 -0800 Subject: [PATCH 387/436] Add 1ad4good bidder (#4081) * adding bidder code and A bidder for non-profit free ads. more info about this bidder project can be found on project site http://1ad4good.org * removed unused code test coverage is improved to >80% tested for instream video support * removed some legacy code, unused params * hardcoding https to endpoint --- modules/1ad4goodBidAdapter.js | 399 ++++++++++++++ modules/1ad4goodBidAdapter.md | 87 +++ test/spec/modules/1ad4goodBidAdapter_spec.js | 548 +++++++++++++++++++ 3 files changed, 1034 insertions(+) create mode 100644 modules/1ad4goodBidAdapter.js create mode 100644 modules/1ad4goodBidAdapter.md create mode 100644 test/spec/modules/1ad4goodBidAdapter_spec.js diff --git a/modules/1ad4goodBidAdapter.js b/modules/1ad4goodBidAdapter.js new file mode 100644 index 00000000000..26057b5e2b2 --- /dev/null +++ b/modules/1ad4goodBidAdapter.js @@ -0,0 +1,399 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const BIDDER_CODE = '1ad4good'; +const URL = 'https://hb.1ad4good.org/prebid'; +const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', + 'startdelay', 'skippable', 'playback_method', 'frameworks']; +const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language']; +const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately +const SOURCE = 'pbjs'; +const MAX_IMPS_PER_REQUEST = 15; + +export const spec = { + code: BIDDER_CODE, + aliases: ['adsforgood', 'ads4good', '1adsforgood'], + 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.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 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 appDeviceObjBid = find(bidRequests, hasAppDeviceInfo); + let appDeviceObj; + if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app) { + appDeviceObj = {}; + Object.keys(appDeviceObjBid.params.app) + .filter(param => includes(APP_DEVICE_PARAMS, param)) + .forEach(param => appDeviceObj[param] = appDeviceObjBid.params.app[param]); + } + + const appIdObjBid = find(bidRequests, hasAppId); + let appIdObj; + if (appIdObjBid && appIdObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) { + appIdObj = { + appid: appIdObjBid.params.app.id + }; + } + + const payload = { + tags: [...tags], + user: userObj, + sdk: { + source: SOURCE, + version: '$prebid.version$' + } + }; + + if (appDeviceObjBid) { + payload.device = appDeviceObj + } + if (appIdObjBid) { + payload.app = appIdObj; + } + + if (bidderRequest && bidderRequest.gdprConsent) { + // note - objects for impbus use underscore instead of camelCase + payload.gdpr_consent = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: bidderRequest.gdprConsent.gdprApplies + }; + } + + if (bidderRequest && bidderRequest.refererInfo) { + let refererinfo = { + rd_ref: encodeURIComponent(bidderRequest.refererInfo.referer), + rd_top: bidderRequest.refererInfo.reachedTop, + rd_ifs: bidderRequest.refererInfo.numIframes, + rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') + } + payload.referrer_detection = refererinfo; + } + + const request = formatRequest(payload, bidderRequest); + return 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: 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; + }, + + transformBidParams: function(params, isOpenRtb) { + params = utils.convertTypes({ + 'placementId': 'number', + 'keywords': utils.transformBidderParamKeywords + }, params); + + if (isOpenRtb) { + params.use_pmt_rule = (typeof params.usePaymentRule === 'boolean') ? params.usePaymentRule : false; + if (params.usePaymentRule) { delete params.usePaymentRule; } + + if (isPopulatedArray(params.keywords)) { + params.keywords.forEach(deleteValues); + } + + Object.keys(params).forEach(paramKey => { + let convertedKey = utils.convertCamelToUnderscore(paramKey); + if (convertedKey !== paramKey) { + params[convertedKey] = params[paramKey]; + delete params[paramKey]; + } + }); + } + + return params; + }, + + /** + * Add element selector to javascript tracker to improve native viewability + * @param {Bid} bid + */ + onBidWon: function(bid) { + } +} + +function isPopulatedArray(arr) { + return !!(utils.isArray(arr) && arr.length > 0); +} + +function deleteValues(keyPairObj) { + if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { + delete keyPairObj.value; + } +} + +function formatRequest(payload, bidderRequest) { + let request = []; + + if (payload.tags.length > MAX_IMPS_PER_REQUEST) { + const clonedPayload = utils.deepClone(payload); + + utils.chunk(payload.tags, MAX_IMPS_PER_REQUEST).forEach(tags => { + clonedPayload.tags = tags; + const payloadString = JSON.stringify(clonedPayload); + request.push({ + method: 'POST', + url: URL, + data: payloadString, + bidderRequest + }); + }); + } else { + const payloadString = JSON.stringify(payload); + request = { + method: 'POST', + url: URL, + data: payloadString, + bidderRequest + }; + } + + return request; +} + +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @param rtbBid + * @param bidderRequest + * @return Bid + */ +function newBid(serverBid, rtbBid, bidderRequest) { + const bidRequest = utils.getBidRequest(serverBid.uuid, [bidderRequest]); + const bid = { + requestId: serverBid.uuid, + cpm: rtbBid.cpm, + creativeId: rtbBid.creative_id, + dealId: rtbBid.deal_id, + currency: 'USD', + netRevenue: true, + ttl: 300, + adUnitCode: bidRequest.adUnitCode, + ads4good: { + buyerMemberId: rtbBid.buyer_member_id, + dealPriority: rtbBid.deal_priority, + dealCode: rtbBid.deal_code + } + }; + + if (rtbBid.advertiser_id) { + bid.meta = Object.assign({}, bid.meta, { advertiserId: rtbBid.advertiser_id }); + } + + if (rtbBid.rtb.video) { + Object.assign(bid, { + width: rtbBid.rtb.video.player_width, + height: rtbBid.rtb.video.player_height, + vastUrl: rtbBid.rtb.video.asset_url, + vastImpUrl: rtbBid.notify_url, + ttl: 3600 + }); + } 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); + } + if (bid.params.cpm) { + tag.cpm = bid.params.cpm; + } + 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)) { + let keywords = utils.transformBidderParamKeywords(bid.params.keywords); + + if (keywords.length > 0) { + keywords.forEach(deleteValues); + } + tag.keywords = keywords; + } + + 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 (bid.renderer) { + tag.video = Object.assign({}, tag.video, {custom_renderer_present: true}); + } + + if ( + (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || + (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) + ) { + 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 hasAppDeviceInfo(bid) { + if (bid.params) { + return !!bid.params.app + } +} + +function hasAppId(bid) { + if (bid.params && bid.params.app) { + return !!bid.params.app.id + } + return !!bid.params.app +} + +function getRtbBid(tag) { + return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); +} + +function parseMediaType(rtbBid) { + const adType = rtbBid.ad_type; + if (adType === VIDEO) { + return VIDEO; + } else { + return BANNER; + } +} + +registerBidder(spec); diff --git a/modules/1ad4goodBidAdapter.md b/modules/1ad4goodBidAdapter.md new file mode 100644 index 00000000000..1e9dfe5e04c --- /dev/null +++ b/modules/1ad4goodBidAdapter.md @@ -0,0 +1,87 @@ +# Overview + +``` +Module Name: 1ad4good Bid Adapter +Module Type: Bidder Adapter +Maintainer: info@1ad4good.org +``` + +# Description + +Connects to 1ad4good exchange for bids. + +1ad4good bid adapter supports Banner and Video (instream). + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: '1ad4good', + params: { + placementId: 13144370 + } + }] + }, + // Video instream adUnit + { + code: 'video-instream', + sizes: [[640, 480]], + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'instream' + }, + }, + bids: [{ + bidder: '1ad4good', + params: { + placementId: 13232361, + video: { + skippable: true, + playback_methods: ['auto_play_sound_off'] + } + } + }] + }, + + // Banner adUnit in a App Webview + // Only use this for situations where prebid.js is in a webview of an App + // See Prebid Mobile for displaying ads via an SDK + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + } + bids: [{ + bidder: '1ad4good', + params: { + placementId: 13144370, + app: { + id: "B1O2W3M4AN.com.prebid.webview", + geo: { + lat: 40.0964439, + lng: -75.3009142 + }, + device_id: { + idfa: "4D12078D-3246-4DA4-AD5E-7610481E7AE", // Apple advertising identifier + aaid: "38400000-8cf0-11bd-b23e-10b96e40000d", // Android advertising identifier + md5udid: "5756ae9022b2ea1e47d84fead75220c8", // MD5 hash of the ANDROID_ID + sha1udid: "4DFAA92388699AC6539885AEF1719293879985BF", // SHA1 hash of the ANDROID_ID + windowsadid: "750c6be243f1c4b5c9912b95a5742fc5" // Windows advertising identifier + } + } + } + }] + } +]; +``` diff --git a/test/spec/modules/1ad4goodBidAdapter_spec.js b/test/spec/modules/1ad4goodBidAdapter_spec.js new file mode 100644 index 00000000000..316a5c13233 --- /dev/null +++ b/test/spec/modules/1ad4goodBidAdapter_spec.js @@ -0,0 +1,548 @@ +import { expect } from 'chai'; +import { spec } from 'modules/1ad4goodBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import * as bidderFactory from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; +import { config } from 'src/config'; + +const ENDPOINT = 'https://hb.1ad4good.org/prebid'; + +describe('AdforgoodAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': '1ad4good', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': '1ad4good', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should parse out private sizes', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + 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', function () { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.sdk).to.exist; + expect(payload.sdk).to.deep.equal({ + source: 'pbjs', + version: '$prebid.version$' + }); + }); + + it('should populate the ad_types array on all requests', function () { + ['banner', 'video'].forEach(type => { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes[type] = {}; + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].ad_types).to.deep.equal([type]); + }); + }); + + it('should populate the ad_types array on outstream requests', function () { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes.video = {context: 'outstream'}; + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].ad_types).to.deep.equal(['video']); + }); + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); + + it('should attach valid video params to the tag', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + video: { + id: 123, + minduration: 100, + foobar: 'invalid' + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tags[0].video).to.deep.equal({ + id: 123, + minduration: 100 + }); + }); + + it('should add video property when adUnit includes a renderer', function () { + const videoData = { + mediaTypes: { + video: { + context: 'outstream', + mimes: ['video/mp4'] + } + }, + params: { + placementId: '10433394', + video: { + skippable: true, + playback_method: ['auto_play_sound_off'] + } + } + }; + + let bidRequest1 = deepClone(bidRequests[0]); + bidRequest1 = Object.assign({}, bidRequest1, videoData, { + renderer: { + url: 'http://test.renderer.url', + render: function () {} + } + }); + + let bidRequest2 = deepClone(bidRequests[0]); + bidRequest2.adUnitCode = 'adUnit_code_2'; + bidRequest2 = Object.assign({}, bidRequest2, videoData); + + const request = spec.buildRequests([bidRequest1, bidRequest2]); + const payload = JSON.parse(request.data); + expect(payload.tags[0].video).to.deep.equal({ + skippable: true, + playback_method: ['auto_play_sound_off'], + custom_renderer_present: true + }); + expect(payload.tags[1].video).to.deep.equal({ + skippable: true, + playback_method: ['auto_play_sound_off'] + }); + }); + + it('should attach valid user params to the tag', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + user: { + externalUid: '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({ + externalUid: '123', + }); + }); + + // it('should always populated tags[].sizes with 1,1 for native if otherwise not defined', function () { + // let bidRequest = Object.assign({}, + // bidRequests[0], + // { + // mediaType: 'native', + // nativeParams: { + // image: { required: true } + // } + // } + // ); + // bidRequest.sizes = [[150, 100], [300, 250]]; + + // let request = spec.buildRequests([bidRequest]); + // let payload = JSON.parse(request.data); + // expect(payload.tags[0].sizes).to.deep.equal([{width: 150, height: 100}, {width: 300, height: 250}]); + + // delete bidRequest.sizes; + + // request = spec.buildRequests([bidRequest]); + // payload = JSON.parse(request.data); + + // expect(payload.tags[0].sizes).to.deep.equal([{width: 1, height: 1}]); + // }); + + it('should convert keyword params to proper form and attaches to request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + emptyStr: '', + emptyArr: [''], + badValue: {'foo': 'bar'} // should be dropped + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].keywords).to.deep.equal([{ + 'key': 'single', + 'value': ['val'] + }, { + 'key': 'singleArr', + 'value': ['val'] + }, { + 'key': 'singleArrNum', + 'value': ['5'] + }, { + 'key': 'multiValMixed', + 'value': ['value1', '2', 'value3'] + }, { + 'key': 'singleValNum', + 'value': ['123'] + }, { + 'key': 'emptyStr' + }, { + 'key': 'emptyArr' + }]); + }); + + it('should add payment rules to the request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + usePaymentRule: true + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].use_pmt_rule).to.equal(true); + }); + + it('should add gdpr consent information to the request', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': '1ad4good', + '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; + }); + + it('supports sending hybrid mobile app parameters', function () { + let appRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + app: { + id: 'B1O2W3M4AN.com.prebid.webview', + geo: { + lat: 40.0964439, + lng: -75.3009142 + }, + device_id: { + idfa: '4D12078D-3246-4DA4-AD5E-7610481E7AE', // Apple advertising identifier + aaid: '38400000-8cf0-11bd-b23e-10b96e40000d', // Android advertising identifier + md5udid: '5756ae9022b2ea1e47d84fead75220c8', // MD5 hash of the ANDROID_ID + sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', // SHA1 hash of the ANDROID_ID + windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' // Windows advertising identifier + } + } + } + } + ); + const request = spec.buildRequests([appRequest]); + const payload = JSON.parse(request.data); + expect(payload.app).to.exist; + expect(payload.app).to.deep.equal({ + appid: 'B1O2W3M4AN.com.prebid.webview' + }); + expect(payload.device.device_id).to.exist; + expect(payload.device.device_id).to.deep.equal({ + aaid: '38400000-8cf0-11bd-b23e-10b96e40000d', + idfa: '4D12078D-3246-4DA4-AD5E-7610481E7AE', + md5udid: '5756ae9022b2ea1e47d84fead75220c8', + sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', + windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' + }); + expect(payload.device.geo).to.exist; + expect(payload.device.geo).to.deep.equal({ + lat: 40.0964439, + lng: -75.3009142 + }); + }); + + it('should add referer info to payload', function () { + const bidRequest = Object.assign({}, bidRequests[0]) + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' + ] + } + } + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.referrer_detection).to.exist; + expect(payload.referrer_detection).to.deep.equal({ + rd_ref: 'http%3A%2F%2Fexample.com%2Fpage.html', + rd_top: true, + rd_ifs: 2, + rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') + }); + }); + }) + + describe('interpretResponse', function () { + let bfStub; + before(function() { + bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); + }); + + after(function() { + bfStub.restore(); + }); + + 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, + 'viewability': { + 'config': '' + }, + 'rtb': { + 'banner': { + 'content': '', + 'width': 300, + 'height': 250 + }, + 'trackers': [ + { + 'impression_urls': [ + 'http://lax1-ib.adnxs.com/impression' + ], + 'video_events': {} + } + ] + } + } + ] + } + ] + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true, + 'adUnitCode': 'code', + 'ads4good': { + 'buyerMemberId': 958 + } + } + ]; + let bidderRequest = { + bids: [{ + bidId: '3db3773286ee59', + adUnitCode: 'code' + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + let response = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '84ab500420319d', + 'tag_id': 5976557, + 'auction_id': '297492697822162468', + 'nobid': true + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + + it('handles non-banner media responses', function () { + let response = { + 'tags': [{ + 'uuid': '84ab500420319d', + 'ads': [{ + 'ad_type': 'video', + 'cpm': 0.500000, + 'notify_url': 'imptracker.com', + 'rtb': { + 'video': { + 'content': '' + } + }, + 'javascriptTrackers': '' + }] + }] + }; + let bidderRequest = { + bids: [{ + bidId: '84ab500420319d', + adUnitCode: 'code' + }] + } + + 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('should add deal_priority and deal_code', function() { + let responseWithDeal = deepClone(response); + responseWithDeal.tags[0].ads[0].deal_priority = 'high'; + responseWithDeal.tags[0].ads[0].deal_code = '123'; + + let bidderRequest = { + bids: [{ + bidId: '3db3773286ee59', + adUnitCode: 'code' + }] + } + let result = spec.interpretResponse({ body: responseWithDeal }, {bidderRequest}); + expect(Object.keys(result[0].ads4good)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); + }); + + it('should add advertiser id', function() { + let responseAdvertiserId = deepClone(response); + responseAdvertiserId.tags[0].ads[0].advertiser_id = '123'; + + let bidderRequest = { + bids: [{ + bidId: '3db3773286ee59', + adUnitCode: 'code' + }] + } + let result = spec.interpretResponse({ body: responseAdvertiserId }, {bidderRequest}); + expect(Object.keys(result[0].meta)).to.include.members(['advertiserId']); + }) + }); +}); From 31036a6f9c1bc7e1d0e1926ff30b63cc91a8d4a9 Mon Sep 17 00:00:00 2001 From: Jozef Bartek <31618107+jbartek25@users.noreply.github.com> Date: Mon, 11 Nov 2019 17:03:04 +0100 Subject: [PATCH 388/436] Improve Digital adapter fix: don't send sizes for instream video (#4427) * Bid floor, https, native ad update * Update the ad server protocol module * Adding referrer * Improve Digital support for video * Improve Digital adapter: video * adapter version -> 6.0.0 * Improve Digital adapter: don't send sizes for video --- modules/improvedigitalBidAdapter.js | 14 +++++++++----- .../modules/improvedigitalBidAdapter_spec.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 4ee2226395b..cd7ab1bd50b 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -6,7 +6,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'; const BIDDER_CODE = 'improvedigital'; export const spec = { - version: '6.0.0', + version: '6.0.1', code: BIDDER_CODE, aliases: ['id'], supportedMediaTypes: [BANNER, NATIVE, VIDEO], @@ -170,6 +170,12 @@ export const spec = { } }; +function isInstreamVideo(bid) { + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + return bid.mediaType === 'video' || (videoMediaType && context !== 'outstream'); +} + function getNormalizedBidRequest(bid) { let adUnitId = utils.getBidIdParameter('adUnitCode', bid) || null; let placementId = utils.getBidIdParameter('placementId', bid.params) || null; @@ -189,9 +195,7 @@ function getNormalizedBidRequest(bid) { const bidFloorCur = utils.getBidIdParameter('bidFloorCur', bid.params); let normalizedBidRequest = {}; - const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (bid.mediaType === 'video' || (videoMediaType && context !== 'outstream')) { + if (isInstreamVideo(bid)) { normalizedBidRequest.adTypes = [ VIDEO ]; } if (placementId) { @@ -209,7 +213,7 @@ function getNormalizedBidRequest(bid) { normalizedBidRequest.keyValues = keyValues; } - if (config.getConfig('improvedigital.usePrebidSizes') === true && bid.sizes && bid.sizes.length > 0) { + if (config.getConfig('improvedigital.usePrebidSizes') === true && !isInstreamVideo(bid) && bid.sizes && bid.sizes.length > 0) { normalizedBidRequest.format = bid.sizes; } else if (singleSizeFilter && singleSizeFilter.w && singleSizeFilter.h) { normalizedBidRequest.size = {}; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 2d9d51c0d68..8ac8c8e85df 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -212,6 +212,22 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']); }); + it('should not set Prebid sizes in bid request for instream video', function () { + const getConfigStub = sinon.stub(config, 'getConfig'); + getConfigStub.withArgs('improvedigital.usePrebidSizes').returns(true); + const bidRequest = Object.assign({}, simpleBidRequest); + bidRequest.mediaTypes = { + video: { + context: 'instream', + playerSize: [640, 480] + } + }; + const request = spec.buildRequests([bidRequest])[0]; + const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length))); + expect(params.bid_request.imp[0].banner.format).to.not.exist; + getConfigStub.restore(); + }); + it('should not set ad type for outstream video', function() { const bidRequest = Object.assign({}, simpleBidRequest); bidRequest.mediaTypes = { From 639eec824fe9cfa0c8d42cdbdbfd1f19e365a8db Mon Sep 17 00:00:00 2001 From: Richard Lee <14349+dlackty@users.noreply.github.com> Date: Tue, 12 Nov 2019 06:54:19 +0800 Subject: [PATCH 389/436] Fix a typo in code comment (#4450) --- modules/adpod.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/adpod.js b/modules/adpod.js index 923912d7282..8c352b67d04 100644 --- a/modules/adpod.js +++ b/modules/adpod.js @@ -1,6 +1,6 @@ /** * This module houses the functionality to evaluate and process adpod adunits/bids. Specifically there are several hooked functions, - * that either supplement the base function (ie to check something additional or unique to adpod objects) or to replace the base funtion + * that either supplement the base function (ie to check something additional or unique to adpod objects) or to replace the base function * entirely when appropriate. * * Brief outline of each hook: From bcd013d9b289702060e9bdb6a4adcbb2177f03e1 Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Tue, 12 Nov 2019 04:33:57 +0530 Subject: [PATCH 390/436] Inventory id and schain support for display (#4426) * supporting schain --- modules/oneVideoBidAdapter.js | 38 ++++++++++---------- test/spec/modules/oneVideoBidAdapter_spec.js | 6 ++-- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 99d976e9efe..6243bf0497e 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory'; const BIDDER_CODE = 'oneVideo'; export const spec = { code: 'oneVideo', - ENDPOINT: '//ads.adaptv.advertising.com/rtb/openrtb?ext_id=', + ENDPOINT: 'https://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', @@ -45,7 +45,9 @@ export const spec = { return bids.map(bid => { return { method: 'POST', - url: location.protocol + spec.ENDPOINT + bid.params.pubId, + /** removing adding local protocal since we + * can get cookie data only if we call with https. */ + url: spec.ENDPOINT + bid.params.pubId, data: getRequestData(bid, consentData), bidRequest: bid } @@ -193,28 +195,12 @@ function getRequestData(bid, consentData) { if (bid.params.video.placement) { bidData.imp[0].video.placement = bid.params.video.placement } - if (bid.params.video.inventoryid) { - bidData.imp[0].ext.inventoryid = bid.params.video.inventoryid - } if (bid.params.video.rewarded) { bidData.imp[0].ext.rewarded = bid.params.video.rewarded } if (bid.params.site && bid.params.site.id) { bidData.site.id = bid.params.site.id } - if (bid.params.video.sid) { - bidData.source = { - ext: { - schain: { - complete: 1, - nodes: [{ - sid: bid.params.video.sid, - rid: bidData.id, - }] - } - } - } - } } else if (bid.params.video.display == 1) { bidData.imp[0].banner = { mimes: bid.params.video.mimes, @@ -223,6 +209,22 @@ function getRequestData(bid, consentData) { pos: bid.params.video.position, }; } + if (bid.params.video.inventoryid) { + bidData.imp[0].ext.inventoryid = bid.params.video.inventoryid + } + if (bid.params.video.sid) { + bidData.source = { + ext: { + schain: { + complete: 1, + nodes: [{ + sid: bid.params.video.sid, + rid: bidData.id, + }] + } + } + } + } if (isConsentRequired(consentData)) { bidData.regs = { ext: { diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 1de413ae596..eccfda0cef7 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -107,7 +107,7 @@ describe('OneVideoBidAdapter', function () { it('should create a POST request for every bid', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].method).to.equal('POST'); - expect(requests[0].url).to.equal(location.protocol + spec.ENDPOINT + bidRequest.params.pubId); + expect(requests[0].url).to.equal(spec.ENDPOINT + bidRequest.params.pubId); }); it('should attach the bid request object', function () { @@ -240,7 +240,8 @@ describe('OneVideoBidAdapter', function () { position: 1, delivery: [2], playbackmethod: [1, 5], - placement: 123, + placement: 1, + inventoryid: 123, sid: 134, display: 1 }, @@ -261,6 +262,7 @@ describe('OneVideoBidAdapter', function () { expect(data.imp[0].banner.w).to.equal(width); expect(data.imp[0].banner.h).to.equal(height); expect(data.imp[0].banner.pos).to.equal(position); + expect(data.imp[0].ext.inventoryid).to.equal(bidRequest.params.video.inventoryid); expect(data.imp[0].banner.mimes).to.equal(bidRequest.params.video.mimes); }); it('should send video object when display is other than 1', function () { From 1a230f475fe9b083d8ae9a04df68258b6eaf97d1 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 12 Nov 2019 01:13:01 +0200 Subject: [PATCH 391/436] Update coinzillaBidAdapter.js (#4438) Update sizes const. --- modules/coinzillaBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/coinzillaBidAdapter.js b/modules/coinzillaBidAdapter.js index 6918d47eb10..26ea7bb71e1 100644 --- a/modules/coinzillaBidAdapter.js +++ b/modules/coinzillaBidAdapter.js @@ -31,7 +31,7 @@ export const spec = { return []; } return validBidRequests.map(bidRequest => { - const sizes = utils.parseSizesInput(bidRequest.sizes)[0]; + const sizes = utils.parseSizesInput(bidRequest.params.size || bidRequest.sizes)[0]; const width = sizes.split('x')[0]; const height = sizes.split('x')[1]; const payload = { From e8ff5c63ecf1d880169a31af8d07e576d58df8ee Mon Sep 17 00:00:00 2001 From: skazedo Date: Mon, 11 Nov 2019 18:18:26 -0500 Subject: [PATCH 392/436] Support schain in ZEDO adapter (#4441) * changes to pass schain --- modules/zedoBidAdapter.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/zedoBidAdapter.js b/modules/zedoBidAdapter.js index 64d28f3f1c6..5fbb02e1f3d 100644 --- a/modules/zedoBidAdapter.js +++ b/modules/zedoBidAdapter.js @@ -84,6 +84,10 @@ export const spec = { } data['placements'].push(placement); }); + // adding schain object + if (bidRequests[0].schain) { + data['supplyChain'] = getSupplyChain(bidRequests[0].schain); + } return { method: 'GET', url: SECURE_URL, @@ -154,12 +158,20 @@ export const spec = { } catch (e) { utils.logError(e); } - }, + } + +}; + +function getSupplyChain (supplyChain) { + return { + complete: supplyChain.complete, + nodes: supplyChain.nodes + } }; 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 From 7ba683cf60fc7cb41e84b20cc3650c18529e706f Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 11 Nov 2019 15:29:31 -0800 Subject: [PATCH 393/436] PubMatic supporting updated Criteo User Id module (#4431) * added support for pubcommon, digitrust, id5id * added support for IdentityLink * changed the source for id5 * added unit test cases * changed source param for identityLink * PubMatic supporting updated Criteo User Id module * added a comment to re-start CI --- modules/pubmaticBidAdapter.js | 2 +- test/spec/modules/pubmaticBidAdapter_spec.js | 20 ++++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 73e6d8cfb52..dc22b9c57ae 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -648,7 +648,7 @@ function _handleEids(payload, validBidRequests) { _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.pubcid`), 'pubcommon', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.digitrustid.data.id`), 'digitru.st', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id`), 'id5-sync.com', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.criteortus.${BIDDER_CODE}.userid`), 'criteortus', 1); + _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.criteoId`), 'criteo.com', 1);// replacing criteoRtus _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.idl_env`), 'liveramp.com', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.lipb.lipbid`), 'liveintent.com', 1); _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.parrableid`), 'parrable.com', 1); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index feb64dfe4ac..13d5a91d16a 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1625,16 +1625,16 @@ describe('PubMatic adapter', function () { }); }); - describe('CriteoRTUS Id', function() { + describe('Criteo Id', function() { it('send the criteo id if it is present', function() { bidRequests[0].userId = {}; - bidRequests[0].userId.criteortus = {pubmatic: {userid: 'criteo-rtus-user-id'}}; + bidRequests[0].userId.criteoId = 'criteo-user-id'; let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ - 'source': 'criteortus', + 'source': 'criteo.com', 'uids': [{ - 'id': 'criteo-rtus-user-id', + 'id': 'criteo-user-id', 'atype': 1 }] }]); @@ -1642,23 +1642,19 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; - bidRequests[0].userId.criteortus = {appnexus: {userid: 'criteo-rtus-user-id'}}; + bidRequests[0].userId.criteoId = 1; let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteortus = {pubmatic: {userid: 1}}; + bidRequests[0].userId.criteoId = []; request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteortus = {pubmatic: {userid: []}}; + bidRequests[0].userId.criteoId = null; request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteortus = {pubmatic: {userid: null}}; - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteortus = {pubmatic: {userid: {}}}; + bidRequests[0].userId.criteoId = {}; request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); From 9a78e3ce64ee30a65884ce3187398a45ea0d99c2 Mon Sep 17 00:00:00 2001 From: msm0504 <51493331+msm0504@users.noreply.github.com> Date: Tue, 12 Nov 2019 13:27:02 -0500 Subject: [PATCH 394/436] Remove duplicate param to fix unit tests (#4459) --- modules/rubiconBidAdapter.js | 1 - test/spec/modules/rubiconBidAdapter_spec.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index fddf70229af..0bfe769ac69 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -337,7 +337,6 @@ export const spec = { 'gdpr', 'gdpr_consent', 'rp_schain', - 'rf', 'tpid_tdid', 'tpid_liveintent.com', 'tg_v.LIseg', diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 64c0f450e39..e09fcebceb2 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -2311,7 +2311,7 @@ describe('the rubicon adapter', function () { }); }); - describe.only('Supply Chain Support', function() { + describe('Supply Chain Support', function() { const nodePropsOrder = ['asi', 'sid', 'hp', 'rid', 'name', 'domain']; let bidRequests; let schainConfig; From 4dd31af0d6976058dad22dd933c2b2528c2453f2 Mon Sep 17 00:00:00 2001 From: Vladislav Yatsun Date: Tue, 12 Nov 2019 22:30:00 +0400 Subject: [PATCH 395/436] Brightcom Bid Adapter update for 3.0 (#4343) --- modules/brightcomBidAdapter.js | 7 +++--- modules/brightcomBidAdapter.md | 16 +++++++++---- test/spec/modules/brightcomBidAdapter_spec.js | 24 ++++++++++--------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/modules/brightcomBidAdapter.js b/modules/brightcomBidAdapter.js index 626aa99f5de..862933d076b 100644 --- a/modules/brightcomBidAdapter.js +++ b/modules/brightcomBidAdapter.js @@ -25,9 +25,10 @@ function buildRequests(bidReqs, bidderRequest) { const brightcomImps = []; const publisherId = utils.getBidIdParameter('publisherId', bidReqs[0].params); utils._each(bidReqs, function (bid) { - bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]); - bid.sizes = bid.sizes.filter(size => utils.isArray(size)); - const processedSizes = bid.sizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); + let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; + bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]); + bidSizes = bidSizes.filter(size => utils.isArray(size)); + const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); const element = document.getElementById(bid.adUnitCode); const minSize = _getMinSize(processedSizes); diff --git a/modules/brightcomBidAdapter.md b/modules/brightcomBidAdapter.md index badc6ea94a4..9f9aa0e5dd7 100644 --- a/modules/brightcomBidAdapter.md +++ b/modules/brightcomBidAdapter.md @@ -16,17 +16,25 @@ Brightcom's adapter integration to the Prebid library. var adUnits = [ { code: 'test-leaderboard', - sizes: [[728, 90]], + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, bids: [{ bidder: 'brightcom', params: { - publisherId: 2141020, - bidFloor: 0.01 + publisherId: 2141020, + bidFloor: 0.01 } }] }, { code: 'test-banner', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, bids: [{ bidder: 'brightcom', params: { diff --git a/test/spec/modules/brightcomBidAdapter_spec.js b/test/spec/modules/brightcomBidAdapter_spec.js index 73186250f5b..14ed4d3024d 100644 --- a/test/spec/modules/brightcomBidAdapter_spec.js +++ b/test/spec/modules/brightcomBidAdapter_spec.js @@ -45,10 +45,11 @@ describe('brightcomBidAdapter', function() { 'publisherId': 1234567 }, 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250], - [300, 600] - ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '5fb26ac22bde4', 'bidderRequestId': '4bf93aeb730cb9', 'auctionId': 'ffe9a1f7-7b67-4bda-a8e0-9ee5dc9f442e' @@ -71,10 +72,11 @@ describe('brightcomBidAdapter', function() { 'publisherId': 1234567 }, 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250], - [300, 600] - ], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250], [300, 600]] + } + }, 'bidId': '5fb26ac22bde4', 'bidderRequestId': '4bf93aeb730cb9', 'auctionId': 'ffe9a1f7-7b67-4bda-a8e0-9ee5dc9f442e', @@ -84,7 +86,7 @@ describe('brightcomBidAdapter', function() { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when tagid not passed correctly', function () { + it('should return false when publisherId not passed correctly', function () { bid.params.publisherId = undefined; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -114,7 +116,7 @@ describe('brightcomBidAdapter', function() { }); it('accepts a single array as a size', function() { - bidRequests[0].sizes = [300, 250]; + bidRequests[0].mediaTypes.banner.sizes = [300, 250]; const request = spec.buildRequests(bidRequests); const payload = JSON.parse(request.data); expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]); @@ -169,7 +171,7 @@ describe('brightcomBidAdapter', function() { context('when width or height of the element is zero', function() { it('try to use alternative values', function() { Object.assign(element, { width: 0, height: 0 }); - bidRequests[0].sizes = [[800, 2400]]; + bidRequests[0].mediaTypes.banner.sizes = [[800, 2400]]; const request = spec.buildRequests(bidRequests); const payload = JSON.parse(request.data); expect(payload.imp[0].banner.ext.viewability).to.equal(25); From e979093a6758115101cf034a4ed5aa6ee40e24e1 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 12 Nov 2019 14:39:03 -0500 Subject: [PATCH 396/436] add support for min_height field in pbs native requests (#4434) --- modules/prebidServerBidAdapter/index.js | 7 ++-- .../modules/prebidServerBidAdapter_spec.js | 35 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 638918ef7af..151e880e985 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -510,10 +510,11 @@ const OPEN_RTB_PROTOCOL = { type: imgTypeId, w: utils.deepAccess(params, 'sizes.0'), h: utils.deepAccess(params, 'sizes.1'), - wmin: utils.deepAccess(params, 'aspect_ratios.0.min_width') + wmin: utils.deepAccess(params, 'aspect_ratios.0.min_width'), + hmin: utils.deepAccess(params, 'aspect_ratios.0.min_height') }); - if (!(asset.w || asset.wmin)) { - throw 'invalid img sizes (must provided sizes or aspect_ratios)'; + if (!((asset.w && asset.h) || (asset.hmin && asset.wmin))) { + throw 'invalid img sizes (must provide sizes or min_height & min_width if using aspect_ratios)'; } if (Array.isArray(params.aspect_ratios)) { // pass aspect_ratios as ext data I guess? diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index e99da15ea0d..76860a09ee2 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -41,6 +41,15 @@ const REQUEST = { 'required': true, 'sizes': [989, 742], }, + 'icon': { + 'required': true, + 'aspect_ratios': [{ + 'min_height': 10, + 'min_width': 10, + 'ratio_height': 1, + 'ratio_width': 1 + }] + }, 'sponsoredBy': { 'required': true } @@ -418,6 +427,19 @@ const RESPONSE_OPENRTB_NATIVE = { } } }, + { + 'id': 2, + 'img': { + 'url': 'https://vcdn.adnxs.com/p/creative-image/1a/3e/e9/5b/1a3ee95b-06cd-4260-98c7-0258627c9197.png', + 'w': 127, + 'h': 83, + 'ext': { + 'appnexus': { + 'prevent_crop': 0 + } + } + } + }, { 'id': 0, 'title': { @@ -425,7 +447,7 @@ const RESPONSE_OPENRTB_NATIVE = { } }, { - 'id': 2, + 'id': 3, 'data': { 'value': 'Prebid.org' } @@ -829,6 +851,17 @@ describe('S2S Adapter', function () { 'h': 742 } }, + { + 'required': 1, + 'img': { + 'type': 1, + 'wmin': 10, + 'hmin': 10, + 'ext': { + 'aspectratios': ['1:1'] + } + } + }, { 'required': 1, 'data': { From 85c2f6d3986d8cb8779071e688c39f3a746c3ec9 Mon Sep 17 00:00:00 2001 From: Robert Ray Martinez III Date: Tue, 12 Nov 2019 11:57:51 -0800 Subject: [PATCH 397/436] Supporting Alias via Video Requests (#4460) --- modules/rubiconBidAdapter.js | 12 ++++++++++-- test/spec/modules/rubiconBidAdapter_spec.js | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 0bfe769ac69..7e2b9147746 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -155,7 +155,7 @@ export const spec = { id: bidRequest.adUnitCode, secure: 1, ext: { - rubicon: bidRequest.params + [bidRequest.bidder]: bidRequest.params }, video: utils.deepAccess(bidRequest, 'mediaTypes.video') || {} }], @@ -175,12 +175,20 @@ export const spec = { } } } + + // Add alias if it is there + if (bidRequest.bidder !== 'rubicon') { + data.ext.prebid.aliases = { + [bidRequest.bidder]: 'rubicon' + } + } + const bidFloor = parseFloat(utils.deepAccess(bidRequest, 'params.floor')); if (!isNaN(bidFloor)) { data.imp[0].bidfloor = bidFloor; } // if value is set, will overwrite with same value - data.imp[0].ext.rubicon.video.size_id = determineRubiconVideoSizeId(bidRequest) + data.imp[0].ext[bidRequest.bidder].video.size_id = determineRubiconVideoSizeId(bidRequest) appendSiteAppDevice(data, bidRequest, bidderRequest); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index e09fcebceb2..3de1418b65c 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1282,6 +1282,22 @@ describe('the rubicon adapter', function () { expect(post.ext.prebid.cache.vastxml.returnCreative).to.equal(false) }); + it('should add alias name to PBS Request', function() { + createVideoBidderRequest(); + + bidderRequest.bidderCode = 'superRubicon'; + bidderRequest.bids[0].bidder = 'superRubicon'; + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + + // should have the aliases object sent to PBS + expect(request.data.ext.prebid).to.haveOwnProperty('aliases'); + expect(request.data.ext.prebid.aliases).to.deep.equal({superRubicon: 'rubicon'}); + + // should have the imp ext bidder params be under the alias name not rubicon superRubicon + expect(request.data.imp[0].ext).to.have.property('superRubicon').that.is.an('object'); + expect(request.data.imp[0].ext).to.not.haveOwnProperty('rubicon'); + }); + it('should send correct bidfloor to PBS', function() { createVideoBidderRequest(); From 9871fcdb22ab44aa6baf3afdd63c1439783474d2 Mon Sep 17 00:00:00 2001 From: vincentproxistore <56686565+vincentproxistore@users.noreply.github.com> Date: Tue, 12 Nov 2019 21:12:02 +0100 Subject: [PATCH 398/436] New adapter Proxistore (#4365) * add test adapter and documentation * integration test with hello_world * reset package-lock.json * delete useless conditionnal * make integrate test work * revert hello-world * revert hello_world * fix descriptor * change adUnits for integration test * remove proxistore widget * uncomment file * change sizes * remove useless script tag --- integrationExamples/gpt/hello_world.html | 122 ++++++++--------- .../gpt/proxistore_example.html | 118 +++++++++++++++++ modules/proxistoreBidAdapter.js | 125 ++++++++++++++++++ modules/proxistoreBidAdapter.md | 73 ++++++++++ .../spec/modules/proxistoreBidAdapter_spec.js | 86 ++++++++++++ 5 files changed, 463 insertions(+), 61 deletions(-) create mode 100644 integrationExamples/gpt/proxistore_example.html create mode 100644 modules/proxistoreBidAdapter.js create mode 100644 modules/proxistoreBidAdapter.md create mode 100644 test/spec/modules/proxistoreBidAdapter_spec.js diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index 337c762adc5..d68e65011be 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -8,84 +8,84 @@ --> - - - - + + - - + + - - + + - - - -

Prebid.js Test

-
Div-1
-
- + + + +

Prebid.js Test

+
Div-1
+
+ -
- - + +
+ + diff --git a/integrationExamples/gpt/proxistore_example.html b/integrationExamples/gpt/proxistore_example.html new file mode 100644 index 00000000000..acd95baef2a --- /dev/null +++ b/integrationExamples/gpt/proxistore_example.html @@ -0,0 +1,118 @@ + + + + + + + + + + + + + +

Prebid.js Test

+ +
Div-1
+ +
+ +
+ + + \ No newline at end of file diff --git a/modules/proxistoreBidAdapter.js b/modules/proxistoreBidAdapter.js new file mode 100644 index 00000000000..44d4acadee2 --- /dev/null +++ b/modules/proxistoreBidAdapter.js @@ -0,0 +1,125 @@ +const { registerBidder } = require('../src/adapters/bidderFactory'); +const BIDDER_CODE = 'proxistore'; + +function _getFormatSize(sizeArr) { + return { + width: sizeArr[0], + height: sizeArr[1] + } +} + +function _createServerRequest(bidRequest, bidderRequest) { + const payload = { + bidId: bidRequest.bidId, + auctionId: bidRequest.auctionId, + transactionId: bidRequest.transactionId, + sizes: bidRequest.sizes.map(_getFormatSize), + website: bidRequest.params.website, + language: bidRequest.params.language, + gdpr: { + applies: false + } + }; + + const options = { + contentType: 'application/json', + withCredentials: true + }; + + if (bidderRequest && bidderRequest.gdprConsent) { + if ((typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') && bidderRequest.gdprConsent.gdprApplies) { + payload.gdpr.applies = true; + } + if ((typeof bidderRequest.gdprConsent.consentString === 'string') && bidderRequest.gdprConsent.consentString) { + payload.gdpr['consentString'] = bidderRequest.gdprConsent.consentString; + } + } + + return { + method: 'POST', + url: bidRequest.params.url || '//abs.proxistore.com/' + bidRequest.params.language + '/v3/rtb/prebid', + data: JSON.stringify(payload), + options: options + }; +} + +function _createBidResponse(response) { + return { + requestId: response.requestId, + cpm: response.cpm, + width: response.width, + height: response.height, + ad: response.ad, + ttl: response.ttl, + creativeId: response.creativeId, + currency: response.currency, + netRevenue: response.netRevenue, + vastUrl: response.vastUrl, + vastXml: response.vastXml, + dealId: response.dealId + } +} + +/** + * Determines whether or not the given bid request is valid. + * + * @param bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ +function isBidRequestValid(bid) { + return !!(bid.params.website && bid.params.language); +} + +/** + * Make a server request from the list of BidRequests. + * + * @param bidRequests - an array of bids + * @param bidderRequest + * @return ServerRequest Info describing the request to the server. + */ +function buildRequests(bidRequests, bidderRequest) { + var requests = []; + for (var i = 0; i < bidRequests.length; i++) { + var prebidReq = _createServerRequest(bidRequests[i], bidderRequest); + requests.push(prebidReq); + } + return requests; +} + +/** + * Unpack the response from the server into a list of bids. + * + * @param serverResponse A successful response from the server. + * @param bidRequest Request original server request + * @return An array of bids which were nested inside the server. + */ +function interpretResponse(serverResponse, bidRequest) { + if (serverResponse.body.length > 0) { + return serverResponse.body.map(_createBidResponse); + } else { + return []; + } +} + +/** + * Register the user sync pixels which should be dropped after the auction. + * + * @param syncOptions Which user syncs are allowed? + * @param serverResponses List of server's responses. + * @return The user syncs which should be dropped. + */ +function getUserSyncs(syncOptions, serverResponses) { + return []; +} + +const spec = { + code: BIDDER_CODE, + isBidRequestValid: isBidRequestValid, + buildRequests: buildRequests, + interpretResponse: interpretResponse, + getUserSyncs: getUserSyncs +}; + +registerBidder(spec); + +module.exports = spec; diff --git a/modules/proxistoreBidAdapter.md b/modules/proxistoreBidAdapter.md new file mode 100644 index 00000000000..e958d52c321 --- /dev/null +++ b/modules/proxistoreBidAdapter.md @@ -0,0 +1,73 @@ +# Overview + +``` +Module Name: Proxistore Bid Adapter +Module Type: Bidder Adapter +GDPR compliant: true +``` + +# Description + +Connects any publisher to Proxistore.com's exchange for bids. + +The present document is available [online](https://abs.proxistore.com/scripts/proxistore-prebid-adapter.md); +the companion Javascript file is available [online](https://abs.proxistore.com/scripts/proxistore-prebid-adapter.js) as well. + +# Sample Ad Unit: For Publishers + +Parameters: +* website: __Required__ - Publisher website as registered with Proxistore - __Each publisher must get this value from Proxistore__ +* language: __Required__ - Publisher website language - Must be one of __fr__,__nl__,__es__ + +Example for a website 'example.com' in French + +``` +var adUnits = [ +{ + code: 'half-page', + mediaTypes: { + banner: { + sizes: [[300,600]] + } + }, + bids: [ + { + bidder: 'proxistore', + params: { + website: 'example.com', + language: 'fr' + } + }] +}, +{ + code: 'rectangle', + mediaTypes: { + banner: { + sizes: [[300,250]] + } + }, + bids: [{ + bidder: 'proxistore', + params: { + website: 'example.com', + language: 'fr' + } + }] +}, +{ + code: 'leaderboard', + mediaTypes: { + banner: { + sizes: [[970,250]] + } + }, + bids: [{ + bidder: 'proxistore', + params: { + website: 'example.com', + language: 'fr' + } + }] +} +]; +``` diff --git a/test/spec/modules/proxistoreBidAdapter_spec.js b/test/spec/modules/proxistoreBidAdapter_spec.js new file mode 100644 index 00000000000..302b7634fbc --- /dev/null +++ b/test/spec/modules/proxistoreBidAdapter_spec.js @@ -0,0 +1,86 @@ +import { expect } from 'chai'; +let spec = require('modules/proxistoreBidAdapter'); + +const BIDDER_CODE = 'proxistore'; +describe('ProxistoreBidAdapter', function () { + const bidderRequest = { + 'bidderCode': BIDDER_CODE, + 'auctionId': '1025ba77-5463-4877-b0eb-14b205cb9304', + 'bidderRequestId': '10edf38ec1a719', + 'gdprConsent': { + 'gdprApplies': true, + 'consentString': 'CONSENT_STRING', + } + }; + let bid = { + sizes: [[300, 600]], + params: { + website: 'example.fr', + language: 'fr' + }, + auctionId: 442133079, + bidId: 464646969, + transactionId: 511916005 + }; + describe('isBidRequestValid', function () { + it('it should be true if required params are presents', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const url = '//abs.proxistore.com/fr/v3/rtb/prebid'; + const request = spec.buildRequests([bid], bidderRequest); + it('should return an empty array if no cookie sent', function () { + expect(request).to.be.an('array'); + expect(request.length).to.equal(1); + }); + it('request method should be POST', function () { + expect(request[0].method).to.equal('POST'); + }); + it('should contain a valid url', function () { + expect(request[0].url).equal(url); + }) + }); + + describe('interpretResponse', function () { + const responses = { + body: + [{ + cpm: 6.25, + creativeId: '48fd47c9-ce35-4fda-804b-17e16c8c36ac', + currency: 'EUR', + dealId: '2019-10_e3ecad8e-d07a-4c90-ad46-cd0f306c8960', + height: 600, + netRevenue: true, + requestId: '923756713', + ttl: 10, + vastUrl: null, + vastXml: null, + width: 300, + }] + }; + const badResponse = { body: [] }; + const interpretedResponse = spec.interpretResponse(responses, bid)[0]; + it('should send an empty array if body is empty', function () { + expect(spec.interpretResponse(badResponse, bid)).to.be.an('array'); + expect(spec.interpretResponse(badResponse, bid).length).equal(0); + }); + it('should interprnet the response correctly if it is valid', function () { + expect(interpretedResponse.cpm).equal(6.25); + expect(interpretedResponse.creativeId).equal('48fd47c9-ce35-4fda-804b-17e16c8c36ac'); + expect(interpretedResponse.currency).equal('EUR'); + expect(interpretedResponse.height).equal(600); + expect(interpretedResponse.width).equal(300); + expect(interpretedResponse.requestId).equal('923756713'); + expect(interpretedResponse.netRevenue).to.be.true; + }) + }); + + describe('interpretResponse', function () { + it('should aways return an empty array', function () { + expect(spec.getUserSyncs()).to.be.an('array'); + expect(spec.getUserSyncs().length).equal(0); + }); + }); +}); From e4490ce02095688a4b81fa31902431216aac6670 Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Wed, 13 Nov 2019 11:47:15 -0700 Subject: [PATCH 399/436] Implementation of setBidderConfig and bidder-specific data (#4334) * initial implementation of setBidderConfig * fix ie11 test errors * Support new setBidderConfig format. Include props from both config and bidderConfig in _getConfig * Use core-js Set to avoid issues with IE * Fix tests in IE * put registerSyncs back on bidderFactory * run bidder event methods with bidder config enabled --- src/adapterManager.js | 20 +++- src/adapters/bidderFactory.js | 8 +- src/config.js | 110 +++++++++++++++++++-- src/prebid.js | 1 + src/utils.js | 2 +- test/spec/unit/core/adapterManager_spec.js | 109 +++++++++++++++++++- test/spec/unit/core/bidderFactory_spec.js | 52 +++++----- 7 files changed, 259 insertions(+), 43 deletions(-) diff --git a/src/adapterManager.js b/src/adapterManager.js index 6b1bc9508c8..fa7b7cbb58d 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -1,6 +1,6 @@ /** @module adaptermanger */ -import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp, getBidderRequest } from './utils'; +import { flatten, getBidderCodes, getDefinedParams, shuffle, timestamp, getBidderRequest, bind } from './utils'; import { getLabels, resolveStatus } from './sizeMapping'; import { processNativeAdUnitParams, nativeAdapters } from './native'; import { newBidder } from './adapters/bidderFactory'; @@ -337,9 +337,21 @@ adapterManager.callBids = (adUnits, bidRequests, addBidResponse, doneCb, request request: requestCallbacks.request.bind(null, bidRequest.bidderCode), done: requestCallbacks.done } : undefined); - adapter.callBids(bidRequest, addBidResponse.bind(bidRequest), doneCb.bind(bidRequest), ajax, onTimelyResponse); + config.runWithBidder( + bidRequest.bidderCode, + bind.call( + adapter.callBids, + adapter, + bidRequest, + addBidResponse.bind(bidRequest), + doneCb.bind(bidRequest), + ajax, + onTimelyResponse, + config.callbackWithBidder(bidRequest.bidderCode) + ) + ); }); -} +}; function doingS2STesting() { return _s2sConfig && _s2sConfig.enabled && _s2sConfig.testing && s2sTestingModule; @@ -464,7 +476,7 @@ function tryCallBidderMethod(bidder, method, param) { const spec = adapter.getSpec(); if (spec && spec[method] && typeof spec[method] === 'function') { utils.logInfo(`Invoking ${bidder}.${method}`); - spec[method](param); + config.runWithBidder(bidder, bind.call(spec[method], spec, param)); } } catch (e) { utils.logWarn(`Error calling ${method} of ${bidder}`); diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index d97bac201ea..7ace0f786e7 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -168,7 +168,7 @@ export function newBidder(spec) { return Object.freeze(spec); }, registerSyncs, - callBids: function(bidderRequest, addBidResponse, done, ajax, onTimelyResponse) { + callBids: function(bidderRequest, addBidResponse, done, ajax, onTimelyResponse, configEnabledCallback) { if (!Array.isArray(bidderRequest.bids)) { return; } @@ -216,7 +216,7 @@ export function newBidder(spec) { // 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) + const onResponse = delayExecution(configEnabledCallback(afterAllResponses), requests.length) requests.forEach(processRequest); function formatGetParameters(data) { @@ -233,7 +233,7 @@ export function newBidder(spec) { ajax( `${request.url}${formatGetParameters(request.data)}`, { - success: onSuccess, + success: configEnabledCallback(onSuccess), error: onFailure }, undefined, @@ -247,7 +247,7 @@ export function newBidder(spec) { ajax( request.url, { - success: onSuccess, + success: configEnabledCallback(onSuccess), error: onFailure }, typeof request.data === 'string' ? request.data : JSON.stringify(request.data), diff --git a/src/config.js b/src/config.js index 022f29dd8c1..b5b1e92dd41 100644 --- a/src/config.js +++ b/src/config.js @@ -4,8 +4,10 @@ import { isValidPriceConfig } from './cpmBucketManager'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; +import Set from 'core-js/library/fn/set'; import { parseQS } from './url'; +const from = require('core-js/library/fn/array/from'); const utils = require('./utils'); const CONSTANTS = require('./constants'); @@ -49,6 +51,8 @@ export function newConfig() { let listeners = []; let defaults; let config; + let bidderConfig; + let currBidder = null; function resetConfig() { defaults = {}; @@ -86,7 +90,7 @@ export function newConfig() { if (validatePriceGranularity(val)) { if (typeof val === 'string') { this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM; - } else if (typeof val === 'object') { + } else if (utils.isPlainObject(val)) { this._customPriceBucket = val; this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM; utils.logMessage('Using custom price granularity'); @@ -111,7 +115,7 @@ export function newConfig() { if (validatePriceGranularity(val[item])) { if (typeof val === 'string') { aggregate[item] = (hasGranularity(val[item])) ? val[item] : this._priceGranularity; - } else if (typeof val === 'object') { + } else if (utils.isPlainObject(val)) { aggregate[item] = val[item]; utils.logMessage(`Using custom price granularity for ${item}`); } @@ -182,6 +186,7 @@ export function newConfig() { } config = newConfig; + bidderConfig = {}; function hasGranularity(val) { return find(Object.keys(GRANULARITY_OPTIONS), option => val === GRANULARITY_OPTIONS[option]); @@ -196,7 +201,7 @@ export function newConfig() { if (!hasGranularity(val)) { utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); } - } else if (typeof val === 'object') { + } else if (utils.isPlainObject(val)) { if (!isValidPriceConfig(val)) { utils.logError('Invalid custom price value passed to `setPriceGranularity()`'); return false; @@ -206,6 +211,33 @@ export function newConfig() { } } + /** + * Returns base config with bidder overrides (if there is currently a bidder) + * @private + */ + function _getConfig() { + if (currBidder && bidderConfig && utils.isPlainObject(bidderConfig[currBidder])) { + let currBidderConfig = bidderConfig[currBidder]; + const configTopicSet = new Set(Object.keys(config).concat(Object.keys(currBidderConfig))); + + return from(configTopicSet).reduce((memo, topic) => { + if (!currBidderConfig[topic]) { + memo[topic] = config[topic]; + } else if (!config[topic]) { + memo[topic] = currBidderConfig[topic]; + } else { + if (utils.isPlainObject(currBidderConfig[topic])) { + memo[topic] = Object.assign({}, config[topic], currBidderConfig[topic]); + } else { + memo[topic] = currBidderConfig[topic]; + } + } + return memo; + }, {}); + } + return Object.assign({}, config); + } + /* * Returns configuration object if called without parameters, * or single configuration property if given a string matching a configuration @@ -217,18 +249,25 @@ export function newConfig() { function getConfig(...args) { if (args.length <= 1 && typeof args[0] !== 'function') { const option = args[0]; - return option ? utils.deepAccess(config, option) : config; + return option ? utils.deepAccess(_getConfig(), option) : _getConfig(); } return subscribe(...args); } + /** + * Internal API for modules (such as prebid-server) that might need access to all bidder config + */ + function getBidderConfig() { + return bidderConfig; + } + /* * Sets configuration given an object containing key-value pairs and calls * listeners that were added by the `subscribe` function */ function setConfig(options) { - if (typeof options !== 'object') { + if (!utils.isPlainObject(options)) { utils.logError('setConfig options must be an object'); return; } @@ -239,7 +278,7 @@ export function newConfig() { topics.forEach(topic => { let option = options[topic]; - if (typeof defaults[topic] === 'object' && typeof option === 'object') { + if (utils.isPlainObject(defaults[topic]) && utils.isPlainObject(option)) { option = Object.assign({}, defaults[topic], option); } @@ -254,7 +293,7 @@ export function newConfig() { * @param {object} options */ function setDefaults(options) { - if (typeof defaults !== 'object') { + if (!utils.isPlainObject(defaults)) { utils.logError('defaults must be an object'); return; } @@ -328,13 +367,68 @@ export function newConfig() { .forEach(listener => listener.callback(options)); } + function setBidderConfig(config) { + try { + check(config); + config.bidders.forEach(bidder => { + if (!bidderConfig[bidder]) { + bidderConfig[bidder] = {}; + } + Object.keys(config.config).forEach(topic => { + let option = config.config[topic]; + if (utils.isPlainObject(option)) { + bidderConfig[bidder][topic] = Object.assign({}, bidderConfig[bidder][topic] || {}, option); + } else { + bidderConfig[bidder][topic] = option; + } + }); + }); + } catch (e) { + utils.logError(e); + } + function check(obj) { + if (!utils.isPlainObject(obj)) { + throw 'setBidderConfig bidder options must be an object'; + } + if (!(Array.isArray(obj.bidders) && obj.bidders.length)) { + throw 'setBidderConfig bidder options must contain a bidders list with at least 1 bidder'; + } + if (!utils.isPlainObject(obj.config)) { + throw 'setBidderConfig bidder options must contain a config object'; + } + } + } + + /** + * Internal functions for core to execute some synchronous code while having an active bidder set. + */ + function runWithBidder(bidder, fn) { + currBidder = bidder; + try { + return fn(); + } finally { + currBidder = null; + } + } + function callbackWithBidder(bidder) { + return function(cb) { + return function(...args) { + return runWithBidder(bidder, utils.bind.call(cb, this, ...args)) + } + } + } + resetConfig(); return { getConfig, setConfig, setDefaults, - resetConfig + resetConfig, + runWithBidder, + callbackWithBidder, + setBidderConfig, + getBidderConfig }; } diff --git a/src/prebid.js b/src/prebid.js index 14c63651ba5..44649d7d444 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -780,6 +780,7 @@ $$PREBID_GLOBAL$$.getConfig = config.getConfig; * ``` */ $$PREBID_GLOBAL$$.setConfig = config.setConfig; +$$PREBID_GLOBAL$$.setBidderConfig = config.setBidderConfig; $$PREBID_GLOBAL$$.que.push(() => listenMessagesFromCreative()); diff --git a/src/utils.js b/src/utils.js index ff7ba3b796f..5efc969896e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -954,7 +954,7 @@ export function delayExecution(func, numRequiredCalls) { return function () { numCalls++; if (numCalls === numRequiredCalls) { - func.apply(null, arguments); + func.apply(this, arguments); } } } diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 1933e4a736d..504e4d326ec 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -3,7 +3,8 @@ import adapterManager, { gdprDataHandler } from 'src/adapterManager'; import { getAdUnits, getServerTestingConfig, - getServerTestingsAds + getServerTestingsAds, + getBidRequests } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; @@ -135,6 +136,112 @@ describe('adapterManager tests', function () { sinon.assert.calledOnce(appnexusAdapterMock.callBids); events.off(CONSTANTS.EVENTS.BID_REQUESTED, count); }); + + it('should give bidders access to bidder-specific config', function(done) { + let mockBidders = ['rubicon', 'appnexus', 'pubmatic']; + let bidderRequest = getBidRequests().filter(bidRequest => includes(mockBidders, bidRequest.bidderCode)); + let adUnits = getAdUnits(); + + let bidders = {}; + let results = {}; + let cbCount = 0; + + function mock(bidder) { + bidders[bidder] = adapterManager.bidderRegistry[bidder]; + adapterManager.bidderRegistry[bidder] = { + callBids: function(bidRequest, addBidResponse, done, ajax, timeout, configCallback) { + let myResults = results[bidRequest.bidderCode] = []; + myResults.push(config.getConfig('buildRequests')); + myResults.push(config.getConfig('test1')); + myResults.push(config.getConfig('test2')); + // emulate ajax callback that would register bids + setTimeout(configCallback(() => { + myResults.push(config.getConfig('interpretResponse')); + myResults.push(config.getConfig('afterInterpretResponse')); + if (++cbCount === Object.keys(bidders).length) { + assertions(); + } + }), 1); + done(); + } + } + } + + mockBidders.forEach(bidder => { + mock(bidder); + }); + + config.setConfig({ + buildRequests: { + data: 1 + }, + test1: { speedy: true }, + interpretResponse: 'baseInterpret', + afterInterpretResponse: 'anotherBaseInterpret' + }); + config.setBidderConfig({ + bidders: [ 'appnexus' ], + config: { + buildRequests: { + test: 2 + }, + test1: { fun: { safe: true, cheap: false } }, + interpretResponse: 'appnexusInterpret' + } + }); + config.setBidderConfig({ + bidders: [ 'rubicon' ], + config: { + buildRequests: 'rubiconBuild', + interpretResponse: 'rubiconInterpret' + } + }); + config.setBidderConfig({ + bidders: [ 'appnexus', 'rubicon' ], + config: { + test2: { amazing: true } + } + }); + + adapterManager.callBids(adUnits, bidderRequest, () => {}, () => {}); + + function assertions() { + expect(results).to.deep.equal({ + 'appnexus': [ + { + data: 1, + test: 2 + }, + { fun: { safe: true, cheap: false }, speedy: true }, + { amazing: true }, + 'appnexusInterpret', + 'anotherBaseInterpret' + ], + 'pubmatic': [ + { + data: 1 + }, + { speedy: true }, + undefined, + 'baseInterpret', + 'anotherBaseInterpret' + ], + 'rubicon': [ + 'rubiconBuild', + { speedy: true }, + { amazing: true }, + 'rubiconInterpret', + 'anotherBaseInterpret' + ] + }); + + // restore bid adapters + Object.keys(bidders).forEach(bidder => { + adapterManager.bidderRegistry[bidder] = bidders[bidder]; + }); + done(); + } + }); }); describe('callTimedOutBidders', function () { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 2dcb26061bd..e8ddf52c128 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -33,6 +33,8 @@ function onTimelyResponseStub() { } +let wrappedCallback = config.callbackWithBidder(CODE); + describe('bidders created by newBidder', function () { let spec; let bidder; @@ -71,7 +73,7 @@ describe('bidders created by newBidder', function () { spec.getUserSyncs.returns([]); bidder.callBids({}); - bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids({ bids: 'nothing useful' }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.called).to.equal(false); @@ -85,7 +87,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -99,7 +101,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -113,7 +115,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.onSecondCall().returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -127,7 +129,7 @@ describe('bidders created by newBidder', function () { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.called).to.equal(false); }); @@ -143,7 +145,7 @@ describe('bidders created by newBidder', function () { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -168,7 +170,7 @@ describe('bidders created by newBidder', function () { options: options }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -191,7 +193,7 @@ describe('bidders created by newBidder', function () { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -215,7 +217,7 @@ describe('bidders created by newBidder', function () { options: opt }); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -244,7 +246,7 @@ describe('bidders created by newBidder', function () { } ]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(ajaxStub.calledTwice).to.equal(true); }); @@ -257,7 +259,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.callCount).to.equal(0); }); @@ -297,7 +299,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(spec.interpretResponse.calledOnce).to.equal(true); const response = spec.interpretResponse.firstCall.args[0] @@ -329,7 +331,7 @@ describe('bidders created by newBidder', function () { ]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(spec.interpretResponse.calledTwice).to.equal(true); expect(doneStub.calledOnce).to.equal(true); @@ -360,7 +362,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); @@ -383,7 +385,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1); @@ -402,7 +404,7 @@ describe('bidders created by newBidder', function () { url: 'usersync.com' }]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(userSyncStub.called).to.equal(true); expect(userSyncStub.firstCall.args[0]).to.equal('iframe'); @@ -431,7 +433,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(logErrorSpy.calledOnce).to.equal(true); }); @@ -461,7 +463,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(logErrorSpy.calledOnce).to.equal(true); }); @@ -493,7 +495,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(spec.interpretResponse.called).to.equal(false); expect(doneStub.calledOnce).to.equal(true); @@ -511,7 +513,7 @@ describe('bidders created by newBidder', function () { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.callCount).to.equal(0); expect(doneStub.calledOnce).to.equal(true); @@ -528,7 +530,7 @@ describe('bidders created by newBidder', function () { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]); @@ -674,7 +676,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); @@ -711,7 +713,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.calledOnce).to.equal(false); expect(logErrorSpy.callCount).to.equal(1); @@ -744,7 +746,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); @@ -776,7 +778,7 @@ describe('validate bid response: ', function () { const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); expect(addBidResponseStub.calledOnce).to.equal(true); expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); From cbb1b1fee6b17913e676e4265ff31c3a47f4962a Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Thu, 14 Nov 2019 08:17:13 -0800 Subject: [PATCH 400/436] Prebid 2.40.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 00e47b4c312..3f843bc7b31 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.40.0-pre", + "version": "2.40.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 15c5f125575d80213c819345ec9dde3276d4c1fb Mon Sep 17 00:00:00 2001 From: Mike Chowla Date: Thu, 14 Nov 2019 08:43:27 -0800 Subject: [PATCH 401/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f843bc7b31..9db7109a48e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.40.0", + "version": "2.41.0i-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From cd28151c003286a07d33ccbb5d458191dfb9af11 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Thu, 14 Nov 2019 10:39:38 -0800 Subject: [PATCH 402/436] Conversant Bid Adapter checks pubcid directly (#4430) --- modules/conversantBidAdapter.js | 40 ++++++- .../spec/modules/conversantBidAdapter_spec.js | 100 ++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index a3479a9d1d1..aa0761161f7 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -52,11 +52,14 @@ export const spec = { let siteId = ''; let requestId = ''; let pubcid = null; + let pubcidName = '_pubcid'; const conversantImps = validBidRequests.map(function(bid) { const bidfloor = utils.getBidIdParameter('bidfloor', bid.params); - siteId = utils.getBidIdParameter('site_id', bid.params); + siteId = utils.getBidIdParameter('site_id', bid.params) || siteId; + pubcidName = utils.getBidIdParameter('pubcid_name', bid.params) || pubcidName; + requestId = bid.auctionId; const imp = { @@ -132,6 +135,10 @@ export const spec = { } } + if (!pubcid) { + pubcid = readStoredValue(pubcidName); + } + // Add common id if available if (pubcid) { userExt.fpc = pubcid; @@ -287,4 +294,35 @@ function copyOptProperty(src, dst, dstName) { } } +/** + * Look for a stored value from both cookie and local storage and return the first value found. + * @param key Key for the search + * @return {string} Stored value + */ +function readStoredValue(key) { + let storedValue; + try { + // check cookies first + storedValue = utils.getCookie(key); + + if (!storedValue) { + // check expiration time before reading local storage + const storedValueExp = utils.getDataFromLocalStorage(`${key}_exp`); + if (storedValueExp === '' || (storedValueExp && (new Date(storedValueExp)).getTime() - Date.now() > 0)) { + storedValue = utils.getDataFromLocalStorage(key); + storedValue = storedValue ? decodeURIComponent(storedValue) : storedValue; + } + } + + // deserialize JSON if needed + if (utils.isStr(storedValue) && storedValue.charAt(0) === '{') { + storedValue = JSON.parse(storedValue); + } + } catch (e) { + utils.logError(e); + } + + return storedValue; +} + registerBidder(spec); diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 6c9f0c8e6e5..02a915f0c17 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -415,4 +415,104 @@ describe('Conversant adapter tests', function() { expect(payload).to.have.deep.nested.property('user.ext.consent', ''); expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr'); }); + + describe('direct reading pubcid', function() { + const ID_NAME = '_pubcid'; + const CUSTOM_ID_NAME = 'myid'; + const EXP = '_exp'; + const TIMEOUT = 2000; + + function cleanUp(key) { + window.document.cookie = key + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + localStorage.removeItem(key); + localStorage.removeItem(key + EXP); + } + + function expStr(timeout) { + return (new Date(Date.now() + timeout * 60 * 60 * 24 * 1000)).toUTCString(); + } + + afterEach(() => { + cleanUp(ID_NAME); + cleanUp(CUSTOM_ID_NAME); + }); + + it('reading cookie', function() { + // clone bidRequests + const requests = utils.deepClone(bidRequests); + + // add a pubcid cookie + utils.setCookie(ID_NAME, '12345', expStr(TIMEOUT)); + + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.fpc', '12345'); + }); + + it('reading custom cookie', function() { + // clone bidRequests + const requests = utils.deepClone(bidRequests); + requests[0].params.pubcid_name = CUSTOM_ID_NAME; + + // add a pubcid cookie + utils.setCookie(CUSTOM_ID_NAME, '12345', expStr(TIMEOUT)); + + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.fpc', '12345'); + }); + + it('reading local storage with empty exp time', function() { + // clone bidRequests + const requests = utils.deepClone(bidRequests); + + // add a pubcid in local storage + utils.setDataInLocalStorage(ID_NAME + EXP, ''); + utils.setDataInLocalStorage(ID_NAME, 'abcde'); + + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.fpc', 'abcde'); + }); + + it('reading local storage with valid exp time', function() { + // clone bidRequests + const requests = utils.deepClone(bidRequests); + + // add a pubcid in local storage + utils.setDataInLocalStorage(ID_NAME + EXP, expStr(TIMEOUT)); + utils.setDataInLocalStorage(ID_NAME, 'fghijk'); + + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.fpc', 'fghijk'); + }); + + it('reading expired local storage', function() { + // clone bidRequests + const requests = utils.deepClone(bidRequests); + + // add a pubcid in local storage + utils.setDataInLocalStorage(ID_NAME + EXP, expStr(-TIMEOUT)); + utils.setDataInLocalStorage(ID_NAME, 'lmnopq'); + + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.not.have.deep.nested.property('user.ext.fpc'); + }); + + it('reading local storage with custom name', function() { + // clone bidRequests + const requests = utils.deepClone(bidRequests); + requests[0].params.pubcid_name = CUSTOM_ID_NAME; + + // add a pubcid in local storage + utils.setDataInLocalStorage(CUSTOM_ID_NAME + EXP, expStr(TIMEOUT)); + utils.setDataInLocalStorage(CUSTOM_ID_NAME, 'fghijk'); + + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.fpc', 'fghijk'); + }); + }); }); From 57537ce502f190aa20ae4f4ef0a59a5e59a052c1 Mon Sep 17 00:00:00 2001 From: Rade Popovic <32302052+nanointeractive@users.noreply.github.com> Date: Thu, 14 Nov 2019 23:52:11 +0100 Subject: [PATCH 403/436] Cookie Sync functionality (#4457) * changing PID param value for testing * cookie sync integration * merge from upstream --- modules/nanointeractiveBidAdapter.js | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index a76cc90ac10..13944cd5a35 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -14,6 +14,8 @@ export const SUB_ID = 'subId'; export const REF = 'ref'; export const LOCATION = 'loc'; +var nanoPid = '5a1ec660eb0a191dfa591172'; + export const spec = { code: BIDDER_CODE, @@ -29,7 +31,7 @@ export const spec = { validBidRequests.forEach( bid => payload.push(createSingleBidRequest(bid, bidderRequest)) ); - const url = getEndpointUrl('main') + '/hb'; + const url = getEndpointUrl() + '/hb'; return { method: 'POST', @@ -45,6 +47,23 @@ export const spec = { } }); return bids; + }, + getUserSyncs: function(syncOptions) { + const syncs = []; + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: getEndpointUrl() + '/hb/cookieSync/' + nanoPid + }); + } + + if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: getEndpointUrl() + '/hb/cookieSync/' + nanoPid + }); + } + return syncs; } }; @@ -52,6 +71,9 @@ export const spec = { function createSingleBidRequest(bid, bidderRequest) { const location = utils.deepAccess(bidderRequest, 'refererInfo.referer'); const origin = utils.getOrigin(); + + nanoPid = bid.params[SSP_PLACEMENT_ID] || nanoPid; + const data = { [SSP_PLACEMENT_ID]: bid.params[SSP_PLACEMENT_ID], [NQ]: [createNqParam(bid)], @@ -117,10 +139,9 @@ function isEngineResponseValid(response) { /** * Used mainly for debugging * - * @param type * @returns string */ -function getEndpointUrl(type) { +function getEndpointUrl() { const nanoConfig = config.getConfig('nano'); return (nanoConfig && nanoConfig['endpointUrl']) || END_POINT_URL; } From ff3c9f0aec62c0bc4c712effb7a7996500429a49 Mon Sep 17 00:00:00 2001 From: Matt Quirion Date: Fri, 15 Nov 2019 04:34:14 -0500 Subject: [PATCH 404/436] Staq Adapter: update with meta envelope (#4372) * initial dev * fix staq adapter name * fix hello world staq call * get hello world working again * add user agent collection * fix some unite tests * Add STAQ Analytics Adapter doc * clean up hello world * fix tests to play nice with browserstack * fix around issues with browserstack and deep equals of objects * dump variable env testing since we can't mod user agent stuff in browserstack * Update STAQ adapter to stop using deprecated utils for referrer * remove package-lock.json changes via master rebase * improve call frequency for ref util * change ajax content type * adjust ajax request to not expect whitelisting * remove superflous commented-out code * update event package to use meta information in envelope rather than per event basis * fix formatting * more formatting fixes * more formatting! --- modules/staqAnalyticsAdapter.js | 103 +++++++++--------- .../spec/modules/staqAnalyticsAdapter_spec.js | 65 +++++------ 2 files changed, 84 insertions(+), 84 deletions(-) diff --git a/modules/staqAnalyticsAdapter.js b/modules/staqAnalyticsAdapter.js index 4d8b81b7be2..225f8cdc43d 100644 --- a/modules/staqAnalyticsAdapter.js +++ b/modules/staqAnalyticsAdapter.js @@ -1,10 +1,10 @@ import adapter from '../src/AnalyticsAdapter'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager'; -import {getRefererInfo} from '../src/refererDetection'; -import {parse} from '../src/url'; +import { getRefererInfo } from '../src/refererDetection'; +import { parse } from '../src/url'; import * as utils from '../src/utils'; -import {ajax} from '../src/ajax'; +import { ajax } from '../src/ajax'; const ANALYTICS_VERSION = '1.0.0'; const DEFAULT_QUEUE_TIMEOUT = 4000; @@ -43,50 +43,49 @@ function buildRequestTemplate(connId) { } } -let analyticsAdapter = Object.assign(adapter({analyticsType: 'endpoint'}), - { - track({ eventType, args }) { - if (!analyticsAdapter.context) { - return; - } - let handler = null; - switch (eventType) { - case CONSTANTS.EVENTS.AUCTION_INIT: - if (analyticsAdapter.context.queue) { - analyticsAdapter.context.queue.init(); - } - handler = trackAuctionInit; - break; - case CONSTANTS.EVENTS.BID_REQUESTED: - handler = trackBidRequest; - break; - case CONSTANTS.EVENTS.BID_RESPONSE: - handler = trackBidResponse; - break; - case CONSTANTS.EVENTS.BID_WON: - handler = trackBidWon; - break; - case CONSTANTS.EVENTS.BID_TIMEOUT: - handler = trackBidTimeout; - break; - case CONSTANTS.EVENTS.AUCTION_END: - handler = trackAuctionEnd; - break; - } - if (handler) { - let events = handler(args); +let analyticsAdapter = Object.assign(adapter({ analyticsType: 'endpoint' }), { + track({ eventType, args }) { + if (!analyticsAdapter.context) { + return; + } + let handler = null; + switch (eventType) { + case CONSTANTS.EVENTS.AUCTION_INIT: if (analyticsAdapter.context.queue) { - analyticsAdapter.context.queue.push(events); - if (eventType === CONSTANTS.EVENTS.BID_WON) { - analyticsAdapter.context.queue.updateWithWins(events); - } + analyticsAdapter.context.queue.init(); } - if (eventType === CONSTANTS.EVENTS.AUCTION_END) { - sendAll(); + handler = trackAuctionInit; + break; + case CONSTANTS.EVENTS.BID_REQUESTED: + handler = trackBidRequest; + break; + case CONSTANTS.EVENTS.BID_RESPONSE: + handler = trackBidResponse; + break; + case CONSTANTS.EVENTS.BID_WON: + handler = trackBidWon; + break; + case CONSTANTS.EVENTS.BID_TIMEOUT: + handler = trackBidTimeout; + break; + case CONSTANTS.EVENTS.AUCTION_END: + handler = trackAuctionEnd; + break; + } + if (handler) { + let events = handler(args); + if (analyticsAdapter.context.queue) { + analyticsAdapter.context.queue.push(events); + if (eventType === CONSTANTS.EVENTS.BID_WON) { + analyticsAdapter.context.queue.updateWithWins(events); } } + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { + sendAll(); + } } - }); + } +}); analyticsAdapter.context = {}; @@ -123,17 +122,17 @@ export default analyticsAdapter; function sendAll() { let events = analyticsAdapter.context.queue.popAll(); if (events.length !== 0) { - let req = events.map(event => { - return Object.assign({}, event, analyticsAdapter.context.requestTemplate) - }); + let req = analyticsAdapter.context.requestTemplate; + req.auctionId = analyticsAdapter.context.auctionId; + req.events = events + analyticsAdapter.ajaxCall(JSON.stringify(req)); } } analyticsAdapter.ajaxCall = function ajaxCall(data) { utils.logInfo('SENDING DATA: ' + data); - ajax(`//${analyticsAdapter.context.url}/prebid/${analyticsAdapter.context.connectionId}`, () => { - }, data, {contentType: 'text/plain'}); + ajax(`//${analyticsAdapter.context.url}/prebid/${analyticsAdapter.context.connectionId}`, () => {}, data, { contentType: 'text/plain' }); }; function trackAuctionInit(args) { @@ -166,9 +165,7 @@ function trackAuctionEnd(args) { } function trackBidTimeout(args) { - return args.map(arg => - createHbEvent(arg.auctionId, arg.bidderCode, STAQ_EVENTS.TIMEOUT) - ); + return args.map(arg => createHbEvent(arg.auctionId, arg.bidderCode, STAQ_EVENTS.TIMEOUT)); } function createHbEvent(auctionId, adapter, event, adUnitCode = undefined, value = 0, time = 0, bidWon = undefined, eventArgs) { @@ -206,7 +203,8 @@ function createHbEvent(auctionId, adapter, event, adUnitCode = undefined, value } const UTM_TAGS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', - 'utm_c1', 'utm_c2', 'utm_c3', 'utm_c4', 'utm_c5']; + 'utm_c1', 'utm_c2', 'utm_c3', 'utm_c4', 'utm_c5' +]; const STAQ_PREBID_KEY = 'staq_analytics'; const DIRECT = '(direct)'; const REFERRAL = '(referral)'; @@ -334,7 +332,8 @@ export function getUmtSource(pageUrl, referrer) { function chooseActualUtm(prev, curr) { if (ord(prev) < ord(curr)) { return [true, curr]; - } if (ord(prev) > ord(curr)) { + } + if (ord(prev) > ord(curr)) { return [false, prev]; } else { if (prev.campaign === REFERRAL && prev.content !== curr.content) { diff --git a/test/spec/modules/staqAnalyticsAdapter_spec.js b/test/spec/modules/staqAnalyticsAdapter_spec.js index 33c85d11431..593871fd9d6 100644 --- a/test/spec/modules/staqAnalyticsAdapter_spec.js +++ b/test/spec/modules/staqAnalyticsAdapter_spec.js @@ -1,5 +1,5 @@ -import analyticsAdapter, {ExpiringQueue, getUmtSource, storage} from 'modules/staqAnalyticsAdapter'; -import {expect} from 'chai'; +import analyticsAdapter, { ExpiringQueue, getUmtSource, storage } from 'modules/staqAnalyticsAdapter'; +import { expect } from 'chai'; import adapterManager from 'src/adapterManager'; import CONSTANTS from 'src/constants.json'; @@ -32,60 +32,60 @@ const CAMPAIGN = { c5: '5' }; -describe('', function () { +describe('', function() { let sandbox; - before(function () { + before(function() { sandbox = sinon.sandbox.create(); }); - after(function () { + after(function() { sandbox.restore(); analyticsAdapter.disableAnalytics(); }); - describe('UTM source parser', function () { + describe('UTM source parser', function() { let stubSetItem; let stubGetItem; - before(function () { + before(function() { stubSetItem = sandbox.stub(storage, 'setItem'); stubGetItem = sandbox.stub(storage, 'getItem'); }); - afterEach(function () { + afterEach(function() { sandbox.reset(); }); - it('should parse first direct visit as (direct)', function () { + it('should parse first direct visit as (direct)', function() { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com'); expect(source).to.be.eql(DIRECT); }); - it('should parse visit from google as organic', function () { + it('should parse visit from google as organic', function() { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com', 'https://www.google.com/search?q=pikachu'); expect(source).to.be.eql(GOOGLE_ORGANIC); }); - it('should parse referral visit', function () { + it('should parse referral visit', function() { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://example.com', 'http://lander.com/lander.html'); expect(source).to.be.eql(REFERRER); }); - it('should parse referral visit from same domain as direct', function () { + it('should parse referral visit from same domain as direct', function() { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://lander.com/news.html', 'http://lander.com/lander.html'); expect(source).to.be.eql(DIRECT); }); - it('should parse campaign visit', function () { + it('should parse campaign visit', function() { stubGetItem.withArgs('adk_dpt_analytics').returns(undefined); stubSetItem.returns(undefined); let source = getUmtSource('http://lander.com/index.html?utm_campaign=new_campaign&utm_source=adkernel&utm_medium=email&utm_c1=1&utm_c2=2&utm_c3=3&utm_c4=4&utm_c5=5'); @@ -93,12 +93,12 @@ describe('', function () { }); }); - describe('ExpiringQueue', function () { + describe('ExpiringQueue', function() { let timer; - before(function () { + before(function() { timer = sandbox.useFakeTimers(0); }); - after(function () { + after(function() { timer.restore(); }); @@ -135,7 +135,9 @@ describe('', function () { params: {}, adUnitCode: 'container-1', transactionId: 'de90df62-7fd0-4fbc-8787-92d133a7dc06', - sizes: [[300, 250]], + sizes: [ + [300, 250] + ], bidId: '208750227436c1', bidderRequestId: '1a6fc81528d0f6', auctionId: '5018eb39-f900-4370-b71e-3bb5b48d324f' @@ -176,26 +178,26 @@ describe('', function () { auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' }]; - describe('Analytics adapter', function () { + describe('Analytics adapter', function() { let ajaxStub; let timer; - before(function () { + before(function() { ajaxStub = sandbox.stub(analyticsAdapter, 'ajaxCall'); timer = sandbox.useFakeTimers(0); }); - beforeEach(function () { + beforeEach(function() { sandbox.stub(events, 'getEvents').callsFake(() => { return [] }); }); - afterEach(function () { + afterEach(function() { events.getEvents.restore(); }); - it('should be configurable', function () { + it('should be configurable', function() { adapterManager.registerAnalyticsAdapter({ code: 'staq', adapter: analyticsAdapter @@ -213,14 +215,14 @@ describe('', function () { expect(analyticsAdapter.context).to.have.property('connectionId', 777); }); - it('should handle auction init event', function () { - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, {config: {}, timeout: 3000}); + it('should handle auction init event', function() { + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, { config: {}, timeout: 3000 }); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(1); - expect(ev[0]).to.be.eql({event: 'auctionInit', auctionId: undefined}); + expect(ev[0]).to.be.eql({ event: 'auctionInit', auctionId: undefined }); }); - it('should handle bid request event', function () { + it('should handle bid request event', function() { events.emit(CONSTANTS.EVENTS.BID_REQUESTED, REQUEST); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(2); @@ -233,7 +235,7 @@ describe('', function () { }); }); - it('should handle bid response event', function () { + it('should handle bid response event', function() { events.emit(CONSTANTS.EVENTS.BID_RESPONSE, RESPONSE); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(3); @@ -265,7 +267,7 @@ describe('', function () { }) }); - it('should handle winning bid', function () { + it('should handle winning bid', function() { events.emit(CONSTANTS.EVENTS.BID_WON, RESPONSE); const ev = analyticsAdapter.context.queue.peekAll(); expect(ev).to.have.length(6); @@ -283,7 +285,7 @@ describe('', function () { }); }); - it('should handle auction end event', function () { + it('should handle auction end event', function() { timer.tick(447); events.emit(CONSTANTS.EVENTS.AUCTION_END, RESPONSE); let ev = analyticsAdapter.context.queue.peekAll(); @@ -291,9 +293,8 @@ describe('', function () { expect(ajaxStub.calledOnce).to.be.equal(true); let firstCallArgs0 = ajaxStub.firstCall.args[0]; ev = JSON.parse(firstCallArgs0); - // console.log('AUCTION END EVENT SHAPE ' + JSON.stringify(ev)); - const ev6 = ev[6]; - expect(ev6.connId).to.be.eql(777); + const ev6 = ev['events'][6]; + expect(ev['connId']).to.be.eql(777); expect(ev6.auctionId).to.be.eql('5018eb39-f900-4370-b71e-3bb5b48d324f'); expect(ev6.event).to.be.eql('auctionEnd'); }); From 7aa7dc46e8fa5d9cd700c7777400b0a1f38bdd90 Mon Sep 17 00:00:00 2001 From: rhythmonebhaines <49991465+rhythmonebhaines@users.noreply.github.com> Date: Mon, 18 Nov 2019 00:17:48 -0800 Subject: [PATCH 405/436] Rhythmone Adapter - schain support (#4414) Circle CI failing tests are not related to this PR. --- modules/rhythmoneBidAdapter.js | 10 ++++- test/spec/modules/rhythmoneBidAdapter_spec.js | 40 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index dc818e89f32..6994173f4be 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -163,7 +163,7 @@ function RhythmOneBidAdapter() { } function frameBid(BRs, bidderRequest) { - return { + let bid = { id: BRs[0].bidderRequestId, imp: frameImp(BRs, bidderRequest), site: frameSite(bidderRequest), @@ -181,6 +181,14 @@ function RhythmOneBidAdapter() { } } }; + if (BRs[0].schain) { + bid.source = { + 'ext': { + 'schain': BRs[0].schain + } + } + } + return bid; } function getFirstParam(key, validBidRequests) { diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index b6ac09a6207..29c8de43c16 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -702,6 +702,46 @@ describe('rhythmone adapter tests', function () { expect(openrtbRequest.imp[0].secure).to.equal(1); }); + it('should pass schain', function() { + var schain = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [{ + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 1 + }] + }; + var bidRequestList = [ + { + 'bidder': 'rhythmone', + 'params': { + 'placementId': 'myplacement', + 'zone': 'myzone', + 'path': 'mypath' + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead', + 'schain': schain + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.source.ext.schain).to.deep.equal(schain); + }); + describe('misc interpretResponse', function () { it('No bid response', function() { var noBidResponse = r1adapter.interpretResponse({ From d4fddd33b7cd909bcc4435d1807cec2237266b12 Mon Sep 17 00:00:00 2001 From: binoy-chitale Date: Mon, 18 Nov 2019 14:48:12 +0530 Subject: [PATCH 406/436] Media.net Adapter: Support Prebid 3.0 (#4378) * Media.net Adapter: Support Prebid 3.0 * Media.net Adapter: add tests to increase code coverage --- modules/medianetBidAdapter.js | 36 +- test/spec/modules/medianetBidAdapter_spec.js | 456 +++++++++++++++---- 2 files changed, 407 insertions(+), 85 deletions(-) diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 8236fb0888c..27a20af398c 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -3,9 +3,10 @@ import * as utils from '../src/utils'; import { config } from '../src/config'; import * as url from '../src/url'; import { BANNER, NATIVE } from '../src/mediaTypes'; +import { getRefererInfo } from '../src/refererDetection'; const BIDDER_CODE = 'medianet'; -const BID_URL = '//prebid.media.net/rtb/prebid'; +const BID_URL = 'https://prebid.media.net/rtb/prebid'; const SLOT_VISIBILITY = { NOT_DETERMINED: 0, ABOVE_THE_FOLD: 1, @@ -17,16 +18,32 @@ const EVENTS = { }; const EVENT_PIXEL_URL = 'qsearch-a.akamaihd.net/log'; +let refererInfo = getRefererInfo(); + let mnData = {}; +mnData.urlData = { + domain: url.parse(refererInfo.referer).host, + page: refererInfo.referer, + isTop: refererInfo.reachedTop +} $$PREBID_GLOBAL$$.medianetGlobals = {}; +function getTopWindowReferrer() { + try { + return window.top.document.referrer; + } catch (e) { + return document.referrer; + } +} + function siteDetails(site) { site = site || {}; let siteData = { - domain: site.domain || utils.getTopWindowLocation().host, - page: site.page || utils.getTopWindowUrl(), - ref: site.ref || utils.getTopWindowReferrer() + domain: site.domain || mnData.urlData.domain, + page: site.page || mnData.urlData.page, + ref: site.ref || getTopWindowReferrer(), + isTop: site.isTop || mnData.urlData.isTop }; return Object.assign(siteData, getPageMeta()); @@ -141,8 +158,10 @@ function slotParams(bidRequest) { }, all: bidRequest.params }; - if (bidRequest.sizes.length > 0) { - params.banner = transformSizes(bidRequest.sizes); + let bannerSizes = utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes || []; + + if (bannerSizes.length > 0) { + params.banner = transformSizes(bannerSizes); } if (bidRequest.nativeParams) { try { @@ -252,8 +271,9 @@ function getLoggingData(event, data) { params.cid = $$PREBID_GLOBAL$$.medianetGlobals.cid || ''; params.crid = data.map((adunit) => utils.deepAccess(adunit, 'params.0.crid') || adunit.adUnitCode).join('|'); params.adunit_count = data.length || 0; - params.dn = utils.getTopWindowLocation().host || ''; - params.requrl = utils.getTopWindowUrl() || ''; + params.dn = mnData.urlData.domain || ''; + params.requrl = mnData.urlData.page || ''; + params.istop = mnData.urlData.isTop || ''; params.event = event.name || ''; params.value = event.value || ''; params.rd = event.related_data || ''; diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 336a86a7793..4ab0809a3ed 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -9,12 +9,17 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', - 'sizes': [[300, 250]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]], + } + }, 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -26,7 +31,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', @@ -37,6 +43,51 @@ let VALID_BID_REQUEST = [{ 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'bidRequestsCount': 1 }], + + VALID_BID_REQUEST_WITH_CRID = [{ + 'bidder': 'medianet', + 'params': { + 'crid': 'crid', + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest', + 'isTop': true + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]], + } + }, + 'bidId': '28f8f8130a583e', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 + }, { + 'bidder': 'medianet', + 'params': { + 'crid': 'crid', + 'cid': 'customer_id', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest', + 'isTop': true + } + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-123', + 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + 'sizes': [[300, 251]], + 'bidId': '3f97ca71b1e5c2', + 'bidderRequestId': '1e9b1f07797c1c', + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 + }], + VALID_BID_REQUEST_INVALID_BIDFLOOR = [{ 'bidder': 'medianet', 'params': { @@ -45,12 +96,18 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'sizes': [[300, 250]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]], + } + }, 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -62,12 +119,18 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'sizes': [[300, 251]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 251]], + } + }, 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -80,12 +143,18 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'sizes': [[300, 250]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]], + } + }, 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -127,12 +196,18 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'sizes': [[300, 251]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 251]], + } + }, 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -170,12 +245,18 @@ let VALID_BID_REQUEST = [{ }], VALID_AUCTIONDATA = { 'timeout': config.getConfig('bidderTimeout'), + 'refererInfo': { + referer: 'http://media.net/prebidtest', + stack: ['http://media.net/prebidtest'], + reachedTop: true + } }, VALID_PAYLOAD_INVALID_BIDFLOOR = { 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true }, 'ext': { 'customer_id': 'customer_id', @@ -215,7 +296,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }, { @@ -245,7 +327,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }], @@ -255,7 +338,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true }, 'ext': { 'customer_id': 'customer_id', @@ -295,7 +379,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }, { @@ -326,7 +411,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }], @@ -336,7 +422,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true }, 'ext': { 'customer_id': 'customer_id', @@ -375,7 +462,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }, { @@ -405,7 +493,94 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true + } + } + }], + 'tmax': config.getConfig('bidderTimeout') + }, + VALID_PAYLOAD_WITH_CRID = { + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest', + 'isTop': true + }, + 'ext': { + 'customer_id': 'customer_id', + 'prebid_version': $$PREBID_GLOBAL$$.version, + 'gdpr_applies': false, + 'screen': { + 'w': 1000, + 'h': 1000 + } + }, + 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'imp': [{ + 'id': '28f8f8130a583e', + 'tagid': 'crid', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 + }, + 'banner': [{ + 'w': 300, + 'h': 250 + }], + 'all': { + 'cid': 'customer_id', + 'crid': 'crid', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest', + 'isTop': true + } + } + }, { + 'id': '3f97ca71b1e5c2', + 'tagid': 'crid', + 'ext': { + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 + }, + 'banner': [{ + 'w': 300, + 'h': 251 + }], + 'all': { + 'cid': 'customer_id', + 'crid': 'crid', + 'site': { + 'page': 'http://media.net/prebidtest', + 'domain': 'media.net', + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }], @@ -429,6 +604,9 @@ let VALID_BID_REQUEST = [{ cid: '8CUV090' } }, + PARAMS_MISSING = { + bidder: 'medianet', + }, PARAMS_WITHOUT_CID = { bidder: 'medianet', params: {} @@ -479,68 +657,127 @@ let VALID_BID_REQUEST = [{ 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' - }] + body: { + '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' - }] + body: { + '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' - }] + body: { + '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' + }] + } + } + }, + SERVER_RESPONSE_NOBODY = { + + }, + SERVER_RESPONSE_EMPTY_BIDLIST = { + body: { + 'id': 'd90ca32f-3877-424a-b2f2-6a68988df57a', + 'bidList': 'bid', + 'ext': { + 'csUrl': [{ + 'type': 'image', + 'url': 'http://cs.media.net/cksync.php' + }, { + 'type': 'iframe', + 'url': 'http://contextual.media.net/checksync.php?&vsSync=1' + }] + } + } + + }, + SERVER_RESPONSE_VALID_BID = { + body: { + 'id': 'd90ca32f-3877-424a-b2f2-6a68988df57a', + 'bidList': [{ + 'no_bid': false, + 'requestId': '27210feac00e96', + 'ad': 'ad', + 'width': 300, + 'height': 250, + 'creativeId': '375068987', + 'netRevenue': true, + 'cpm': 0.1 + }], + 'ext': { + 'csUrl': [{ + 'type': 'image', + 'url': 'http://cs.media.net/cksync.php' + }, { + 'type': 'iframe', + 'url': 'http://contextual.media.net/checksync.php?&vsSync=1' + }] + } } }, + SERVER_VALID_BIDS = [{ + 'no_bid': false, + 'requestId': '27210feac00e96', + 'ad': 'ad', + 'width': 300, + 'height': 250, + 'creativeId': '375068987', + 'netRevenue': true, + 'cpm': 0.1 + }], BID_REQUEST_SIZE_AS_1DARRAY = [{ 'bidder': 'medianet', 'params': { @@ -548,12 +785,18 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'sizes': [300, 250], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]], + } + }, 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -565,12 +808,18 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'sizes': [300, 251], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 251]], + } + }, 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', @@ -581,13 +830,20 @@ let VALID_BID_REQUEST = [{ 'consentString': 'consentString', 'gdprApplies': true, }, - 'timeout': 3000 + 'timeout': 3000, + refererInfo: { + referer: 'http://media.net/prebidtest', + stack: ['http://media.net/prebidtest'], + reachedTop: true + } }, VALID_PAYLOAD_FOR_GDPR = { 'site': { 'domain': 'media.net', 'page': 'http://media.net/prebidtest', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true + }, 'ext': { 'customer_id': 'customer_id', @@ -627,7 +883,8 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }, { @@ -657,13 +914,13 @@ let VALID_BID_REQUEST = [{ 'site': { 'page': 'http://media.net/prebidtest', 'domain': 'media.net', - 'ref': 'http://media.net/prebidtest' + 'ref': 'http://media.net/prebidtest', + 'isTop': true } } }], 'tmax': 3000, }; - describe('Media.net bid adapter', function () { let sandbox; beforeEach(function () { @@ -694,6 +951,11 @@ describe('Media.net bid adapter', function () { let isValid = spec.isBidRequestValid(PARAMS_WITH_EMPTY_CID); expect(isValid).to.equal(false); }); + + it('should have missing params', function () { + let isValid = spec.isBidRequestValid(PARAMS_MISSING); + expect(isValid).to.equal(false); + }); }); describe('buildRequests', function () { @@ -743,6 +1005,11 @@ describe('Media.net bid adapter', function () { expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_NATIVE); }); + it('should have valid crid present in bid request', function() { + let bidreq = spec.buildRequests(VALID_BID_REQUEST_WITH_CRID, VALID_AUCTIONDATA); + expect(JSON.parse(bidreq.data)).to.deep.equal(VALID_PAYLOAD_WITH_CRID); + }); + describe('build requests: when page meta-data is available', () => { beforeEach(() => { spec.clearMnData(); @@ -852,6 +1119,11 @@ describe('Media.net bid adapter', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_BOTH_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); }); + + it('should have empty user sync array', function() { + let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_IFRAME_ENABLED, {}); + expect(userSyncs).to.deep.equal([]); + }); }); describe('interpretResponse', function () { @@ -872,5 +1144,35 @@ describe('Media.net bid adapter', function () { let bids = spec.interpretResponse(SERVER_RESPONSE_NOBID, []); expect(bids).to.deep.equal(validBids); }); + + it('should have empty bid response', function() { + let bids = spec.interpretResponse(SERVER_RESPONSE_NOBODY, []); + expect(bids).to.deep.equal([]); + }); + + it('should have valid bids', function () { + let bids = spec.interpretResponse(SERVER_RESPONSE_VALID_BID, []); + expect(bids).to.deep.equal(SERVER_VALID_BIDS); + }); + + it('should have empty bid list', function() { + let validBids = []; + let bids = spec.interpretResponse(SERVER_RESPONSE_EMPTY_BIDLIST, []); + expect(bids).to.deep.equal(validBids); + }); + }); + + describe('onTimeout', function () { + it('should have valid timeout data', function() { + let response = spec.onTimeout({}); + expect(response).to.deep.equal(undefined); + }); + }); + + describe('onBidWon', function () { + it('should have valid bid data', function() { + let response = spec.onBidWon(undefined); + expect(response).to.deep.equal(undefined); + }); }); }); From 4aeb45426dd30e18a9b75088255cdba62344a82d Mon Sep 17 00:00:00 2001 From: Alex Pashkov Date: Mon, 18 Nov 2019 17:23:48 +0200 Subject: [PATCH 407/436] Vi Adapter: Passes additional param in the bid request (#4134) * Add focus check (cherry picked from commit 9d6d6dfb83580d6a5ffed8faa5762db48f8fd44d) * Pass focus as numeric value (cherry picked from commit 9fae56a637f87b0d39cc1d24eeb1f9ff9df88f64) * Add unit test (cherry picked from commit 946710f2e9960b3839613d4bdf730e57ba38a964) --- modules/viBidAdapter.js | 7 ++++++- test/spec/modules/viBidAdapter_spec.js | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/modules/viBidAdapter.js b/modules/viBidAdapter.js index 93ead1c2380..8d8cb06e47e 100644 --- a/modules/viBidAdapter.js +++ b/modules/viBidAdapter.js @@ -302,6 +302,10 @@ export function mergeArrays(hashFn, ...args) { return merged; } +export function documentFocus(doc) { + return typeof doc.hasFocus === 'function' ? +doc.hasFocus() : undefined; +} + const spec = { code: 'vi', supportedMediaTypes: [mediaTypes.VIDEO, mediaTypes.BANNER], @@ -372,7 +376,8 @@ const spec = { ...params }; } - ) + ), + focus: documentFocus(document) }, options: { contentType: 'application/json', diff --git a/test/spec/modules/viBidAdapter_spec.js b/test/spec/modules/viBidAdapter_spec.js index b12d534ff02..8f1c07047ec 100644 --- a/test/spec/modules/viBidAdapter_spec.js +++ b/test/spec/modules/viBidAdapter_spec.js @@ -23,7 +23,8 @@ import { area, get, getViewabilityDescription, - mergeArrays + mergeArrays, + documentFocus } from 'modules/viBidAdapter'; describe('ratioToPercentageCeil', () => { @@ -892,3 +893,19 @@ describe('mergeSizes', () => { ).to.deep.equal([[1, 2], [2, 4], [400, 500], [500, 600]]); }); }); + +describe('documentFocus', () => { + it('calls hasFocus function if it present, converting boolean to an int 0/1 value, returns undefined otherwise', () => { + expect( + documentFocus({ + hasFocus: () => true + }) + ).to.equal(1); + expect( + documentFocus({ + hasFocus: () => false + }) + ).to.equal(0); + expect(documentFocus({})).to.be.undefined; + }); +}); From 486056de06f242d2199def61c28b0ab630632827 Mon Sep 17 00:00:00 2001 From: Ankit Prakash Date: Mon, 18 Nov 2019 08:52:23 -0700 Subject: [PATCH 408/436] Sovrn adapter updates: schain, digitrust, pixel syncing, and 3.0 upgrades (#4385) * schain and digitrust * pixel beacons * unit tests and fixes from testing * Prebid 3.0 updates * review fix * use backwards compatible flatMap impl * update pixel tests * unit test fix * update one more url to ssl * fixed test * review updates --- modules/sovrnBidAdapter.js | 134 +++++---- test/spec/modules/sovrnBidAdapter_spec.js | 340 +++++++++++++++------- 2 files changed, 299 insertions(+), 175 deletions(-) diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 8b08b3ad6be..daaa3da3aac 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,8 +1,7 @@ import * as utils from '../src/utils' +import {parse} from '../src/url' import { registerBidder } from '../src/adapters/bidderFactory' import { BANNER } from '../src/mediaTypes' -const errorUrl = 'https://pcb.aws.lijit.com/c' -let errorpxls = [] export const spec = { code: 'sovrn', @@ -24,14 +23,30 @@ export const spec = { */ buildRequests: function(bidReqs, bidderRequest) { try { - const loc = utils.getTopWindowLocation(); let sovrnImps = []; let iv; + let schain; + let digitrust; + utils._each(bidReqs, function (bid) { + if (!digitrust) { + const bidRequestDigitrust = utils.deepAccess(bid, 'userId.digitrustid.data'); + if (bidRequestDigitrust && (!bidRequestDigitrust.privacy || !bidRequestDigitrust.privacy.optout)) { + digitrust = { + id: bidRequestDigitrust.id, + keyv: bidRequestDigitrust.keyv + } + } + } + if (bid.schain) { + schain = schain || bid.schain; + } iv = iv || utils.getBidIdParameter('iv', bid.params); - bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]) - bid.sizes = bid.sizes.filter(size => utils.isArray(size)) - const processedSizes = bid.sizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) + + let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; + bidSizes = ((utils.isArray(bidSizes) && utils.isArray(bidSizes[0])) ? bidSizes : [bidSizes]) + bidSizes = bidSizes.filter(size => utils.isArray(size)) + const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) sovrnImps.push({ id: bid.bidId, banner: { @@ -43,15 +58,29 @@ export const spec = { bidfloor: utils.getBidIdParameter('bidfloor', bid.params) }); }); + + const page = bidderRequest.refererInfo.referer + + // clever trick to get the domain + const domain = parse(page).hostname + const sovrnBidReq = { id: utils.getUniqueIdentifierStr(), imp: sovrnImps, site: { - domain: loc.host, - page: loc.host + loc.pathname + loc.search + loc.hash + page, + domain } }; + if (schain) { + sovrnBidReq.source = { + ext: { + schain + } + }; + } + if (bidderRequest && bidderRequest.gdprConsent) { sovrnBidReq.regs = { ext: { @@ -63,7 +92,14 @@ export const spec = { }}; } - let url = `//ap.lijit.com/rtb/bid?` + + if (digitrust) { + utils.deepSetValue(sovrnBidReq, 'user.ext.digitrust', { + id: digitrust.id, + keyv: digitrust.keyv + }) + } + + let url = `https://ap.lijit.com/rtb/bid?` + `src=$$REPO_AND_VERSION$$`; if (iv) url += `&iv=${iv}`; @@ -74,7 +110,8 @@ export const spec = { options: {contentType: 'text/plain'} } } catch (e) { - new LogError(e, {bidReqs, bidderRequest}).append() + console.log('error in build:') + console.log(e) } }, @@ -109,74 +146,43 @@ export const spec = { } return sovrnBidResponses } catch (e) { - new LogError(e, {id, seatbid}).append() + console.log('error in interpret:') + console.log(e) } }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { try { let tracks = [] - if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { - let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) - .map(rsp => { return rsp.body.ext.iid }); - let consentString = ''; - if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { - consentString = gdprConsent.consentString + if (serverResponses && serverResponses.length !== 0) { + if (syncOptions.iframeEnabled) { + let iidArr = serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.iid')) + .map(resp => resp.body.ext.iid); + let consentString = ''; + if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + consentString = gdprConsent.consentString + } + if (iidArr[0]) { + tracks.push({ + type: 'iframe', + url: 'https://ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, + }); + } } - if (iidArr[0]) { - tracks.push({ - type: 'iframe', - url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, - }); + + if (syncOptions.pixelEnabled) { + serverResponses.filter(resp => utils.deepAccess(resp, 'body.ext.sync.pixels')) + .reduce((acc, resp) => acc.concat(resp.body.ext.sync.pixels), []) + .map(pixel => pixel.url) + .forEach(url => tracks.push({ type: 'image', url })) } } - if (errorpxls.length && syncOptions.pixelEnabled) { - tracks = tracks.concat(errorpxls) - } + return tracks } catch (e) { - if (syncOptions.pixelEnabled) { - return errorpxls - } return [] } }, } -export class LogError { - constructor(e, data) { - utils.logError(e) - this.error = {} - this.error.t = utils.timestamp() - this.error.m = e.message - this.error.s = e.stack - this.error.d = data - this.error.v = $$REPO_AND_VERSION$$ - this.error.u = utils.getTopWindowLocation().href - this.error.ua = navigator.userAgent - } - buildErrorString(obj) { - return errorUrl + '?b=' + btoa(JSON.stringify(obj)) - } - append() { - let errstr = this.buildErrorString(this.error) - if (errstr.length > 2083) { - delete this.error.d - errstr = this.buildErrorString(this.error) - if (errstr.length > 2083) { - delete this.error.s - errstr = this.buildErrorString(this.error) - if (errstr.length > 2083) { - errstr = this.buildErrorString({m: 'unknown error message', t: this.error.t, u: this.error.u}) - } - } - } - let obj = {type: 'image', url: errstr} - errorpxls.push(obj) - } - static getErrPxls() { - return errorpxls - } -} - registerBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 7179ec00bc3..44adb4d1cbd 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,9 +1,8 @@ -import { expect } from 'chai'; -import { spec, LogError } from 'modules/sovrnBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; -import { SSL_OP_SINGLE_ECDH_USE } from 'constants'; +import {expect} from 'chai'; +import {LogError, spec} from 'modules/sovrnBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT = `//ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; +const ENDPOINT = `https://ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; describe('sovrnBidAdapter', function() { const adapter = newBidder(spec); @@ -55,8 +54,12 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - - const request = spec.buildRequests(bidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); @@ -85,8 +88,13 @@ describe('sovrnBidAdapter', function() { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' - }]; - const request = spec.buildRequests(singleSize) + }] + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + } + const request = spec.buildRequests(singleSize, bidderRequest) const payload = JSON.parse(request.data) expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]) expect(payload.imp[0].banner.w).to.equal(1) @@ -109,7 +117,12 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const request = spec.buildRequests(ivBidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const request = spec.buildRequests(ivBidRequests, bidderRequest); expect(request.url).to.contain('iv=vet') }); @@ -121,20 +134,22 @@ describe('sovrnBidAdapter', function() { 'auctionId': '1d1a030790a475', 'bidderRequestId': '22edbae2733bf6', 'timeout': 3000, - 'gdprConsent': { + gdprConsent: { consentString: consentString, gdprApplies: true + }, + refererInfo: { + referer: 'http://example.com/page.html', } }; bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); + const data = JSON.parse(spec.buildRequests(bidRequests, bidderRequest).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); + expect(data.regs.ext.gdpr).to.exist.and.to.be.a('number'); + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.user.ext.consent).to.exist.and.to.be.a('string'); + expect(data.user.ext.consent).to.equal(consentString); }); it('converts tagid to string', function () { @@ -153,10 +168,86 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475' }]; - const request = spec.buildRequests(ivBidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const request = spec.buildRequests(ivBidRequests, bidderRequest); expect(request.data).to.contain('"tagid":"403370"') - }) + }); + + it('should add schain if present', function() { + const schainRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': 403370 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'directseller.com', + 'sid': '00001', + 'rid': 'BidRequest1', + 'hp': 1 + } + ] + } + }].concat(bidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const data = JSON.parse(spec.buildRequests(schainRequests, bidderRequest).data); + + expect(data.source.ext.schain.nodes.length).to.equal(1) + }); + + it('should add digitrust data if present', function() { + const digitrustRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': 403370 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'userId': { + 'digitrustid': { + 'data': { + 'id': 'digitrust-id-123', + 'keyv': 4 + } + } + } + }].concat(bidRequests); + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + } + }; + const data = JSON.parse(spec.buildRequests(digitrustRequests, bidderRequest).data); + + expect(data.user.ext.digitrust.id).to.equal('digitrust-id-123'); + expect(data.user.ext.digitrust.keyv).to.equal(4); + }); }); describe('interpretResponse', function () { @@ -253,9 +344,9 @@ describe('sovrnBidAdapter', function() { }); }); - describe('getUserSyncs ', () => { - let syncOptions = {iframeEnabled: true, pixelEnabled: true}; - let iframeDisabledSyncOptions = {iframeEnabled: false, pixelEnabled: true}; + describe('getUserSyncs ', function() { + let syncOptions = { iframeEnabled: true, pixelEnabled: false }; + let iframeDisabledSyncOptions = { iframeEnabled: false, pixelEnabled: false }; let serverResponse = [ { 'body': { @@ -287,111 +378,138 @@ describe('sovrnBidAdapter', function() { } ], 'ext': { - 'iid': 13487408 + 'iid': 13487408, + sync: { + pixels: [ + { + url: 'http://idprovider1.com' + }, + { + url: 'http://idprovider2.com' + } + ] + } } }, 'headers': {} } ]; - it('should return if iid present on server response & iframe syncs enabled', () => { - let expectedReturnStatement = [ + + it('should return if iid present on server response & iframe syncs enabled', function() { + const expectedReturnStatement = [ { 'type': 'iframe', - 'url': '//ap.lijit.com/beacon?informer=13487408&gdpr_consent=', + 'url': 'https://ap.lijit.com/beacon?informer=13487408&gdpr_consent=', } - ] - let returnStatement = spec.getUserSyncs(syncOptions, serverResponse); + ]; + const returnStatement = spec.getUserSyncs(syncOptions, serverResponse); expect(returnStatement[0]).to.deep.equal(expectedReturnStatement[0]); - }) + }); - it('should not return if iid missing on server response', () => { - let returnStatement = spec.getUserSyncs(syncOptions, []) + it('should not return if iid missing on server response', function() { + const returnStatement = spec.getUserSyncs(syncOptions, []); expect(returnStatement).to.be.empty; - }) + }); - it('should not return if iframe syncs disabled', () => { - let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse) - expect(returnStatement).to.be.empty - }) - }) - describe('LogError', () => { - it('should build and append an error object', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const data = {name: 'Oscar Hathenswiotch'} - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(1) - const errdata = JSON.parse(atob(errList[0].url.split('=')[1])) - expect(errdata.d.name).to.equal('Oscar Hathenswiotch') - }) - it('should drop data when there is too much', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const tooLong = () => { - let str = '' - for (let i = 0; i < 10000; i++) { - str = str + String.fromCharCode(i % 100) - } - return str - } - const data = {name: 'Oscar Hathenswiotch', tooLong: tooLong()} - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(2) - const errdata = JSON.parse(atob(errList[1].url.split('=')[1])) - expect(errdata.d).to.be.an('undefined') - }) - it('should drop data and stack when there is too much', () => { - const thrown = { - message: 'message', - stack: 'stack' + it('should not return if iframe syncs disabled', function() { + const returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); + expect(returnStatement).to.be.empty; + }); + + it('should include pixel syncs', function() { + let pixelEnabledOptions = { iframeEnabled: false, pixelEnabled: true }; + const resp2 = { + 'body': { + 'id': '546956d68c757f-2', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'a_448326_16c2ada014224bee815a90d2248322f5-2', + 'impid': '2a3826aae345f4', + 'price': 1.0099999904632568, + 'nurl': 'http://localhost/rtb/impression?bannerid=220958&campaignid=3890&rtb_tid=15588614-75d2-40ab-b27e-13d2127b3c2e&rpid=1295&seatid=seat1&zoneid=448326&cb=26900712&tid=a_448326_16c2ada014224bee815a90d2248322f5', + 'adm': 'yo a creative', + 'crid': 'cridprebidrtb', + 'w': 160, + 'h': 600 + }, + { + 'id': 'a_430392_beac4c1515da4576acf6cb9c5340b40c-2', + 'impid': '3cf96fd26ed4c5', + 'price': 1.0099999904632568, + 'nurl': 'http://localhost/rtb/impression?bannerid=220957&campaignid=3890&rtb_tid=5bc0e68b-3492-448d-a6f9-26fa3fd0b646&rpid=1295&seatid=seat1&zoneid=430392&cb=62735099&tid=a_430392_beac4c1515da4576acf6cb9c5340b40c', + 'adm': 'yo a creative', + 'crid': 'cridprebidrtb', + 'w': 300, + 'h': 250 + }, + ] + } + ], + 'ext': { + 'iid': 13487408, + sync: { + pixels: [ + { + url: 'http://idprovider3.com' + }, + { + url: 'http://idprovider4.com' + } + ] + } + } + }, + 'headers': {} } - const tooLong = () => { - let str = '' - for (let i = 0; i < 10000; i++) { - str = str + String.fromCharCode(i % 100) + const returnStatement = spec.getUserSyncs(pixelEnabledOptions, [...serverResponse, resp2]); + expect(returnStatement.length).to.equal(4); + expect(returnStatement).to.deep.include.members([ + { type: 'image', url: 'http://idprovider1.com' }, + { type: 'image', url: 'http://idprovider2.com' }, + { type: 'image', url: 'http://idprovider3.com' }, + { type: 'image', url: 'http://idprovider4.com' } + ]); + }); + }); + + describe('prebid 3 upgrade', function() { + const bidRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] } - return str + }, + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', } - const data = {name: 'Oscar Hathenswiotch'} - thrown.stack = tooLong() - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(3) - const errdata = JSON.parse(atob(errList[2].url.split('=')[1])) - expect(errdata.d).to.be.an('undefined') - expect(errdata.s).to.be.an('undefined') + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + it('gets sizes from mediaTypes.banner', function() { + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) + expect(payload.imp[0].banner.w).to.equal(1) + expect(payload.imp[0].banner.h).to.equal(1) }) - it('should drop send a reduced message when other reduction methods fail', () => { - const thrown = { - message: 'message', - stack: 'stack' - } - const tooLong = () => { - let str = '' - for (let i = 0; i < 10000; i++) { - str = str + String.fromCharCode(i % 100) - } - return str - } - const data = {name: 'Oscar Hathenswiotch'} - thrown.message = tooLong() - const err = new LogError(thrown, data) - err.append() - const errList = LogError.getErrPxls() - expect(errList.length).to.equal(4) - const errdata = JSON.parse(atob(errList[3].url.split('=')[1])) - expect(errdata.d).to.be.an('undefined') - expect(errdata.s).to.be.an('undefined') - expect(errdata.m).to.equal('unknown error message') + + it('gets correct site info', function() { + expect(payload.site.page).to.equal('http://example.com/page.html'); + expect(payload.site.domain).to.equal('example.com'); }) }) }) From 865869ecb5d6ca916588385015627d05a4da8448 Mon Sep 17 00:00:00 2001 From: TheMediaGrid <44166371+TheMediaGrid@users.noreply.github.com> Date: Mon, 18 Nov 2019 19:41:25 +0300 Subject: [PATCH 409/436] TheMediaGrid Bid Adapter update (#4447) * Added Grid Bid Adapter * remove priceType from TheMediaGrid Bid Adapter * Add video support in Grid Bid Adapter * Added test parameter for video slot * update Grid Bid Adapter to set size in response bid * Update Grid Bid Adapter to support identical uids in parameters * Fix typo in test file for Grid Bid Adapter * Update The Grid Media Bidder Adapter to send refererInfo.referer as 'u' parameter in ad request * Hotfix for referrer in Grid Bid Adapter * Grid Bid Adapter: added wrapperType and wrappweVersion to the ad request * TheMediaGrid Bid Adapter: added sync url * TheMediaGrid Bid Adapter: added GDPR params to sync url * TheMediaGrid Bid Adapter: added tests for getUserSyncs function --- modules/gridBidAdapter.js | 30 ++++++++ test/spec/modules/gridBidAdapter_spec.js | 89 +++++++++++++++++++++++- 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index ac9a7d30429..57ab4ff4ed9 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -5,9 +5,12 @@ import { VIDEO, BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'grid'; const ENDPOINT_URL = '//grid.bidswitch.net/hb'; +const SYNC_URL = '//x.bidswitch.net/sync?ssp=iow_labs'; const TIME_TO_LIVE = 360; const RENDERER_URL = '//acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; +let hasSynced = false; + const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', noAdm: 'Bid from response has no adm parameter - ', @@ -136,6 +139,25 @@ export const spec = { } if (errorMessage) utils.logError(errorMessage); return bidResponses; + }, + getUserSyncs: function (syncOptions, responses, gdprConsent) { + if (!hasSynced && syncOptions.pixelEnabled) { + let params = ''; + + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `&gdpr_consent=${gdprConsent.consentString}`; + } + } + + hasSynced = true; + return { + type: 'image', + url: SYNC_URL + params + }; + } } }; @@ -244,4 +266,12 @@ function createRenderer (bid, rendererParams) { return renderer; } +export function resetUserSync() { + hasSynced = false; +} + +export function getSyncUrl() { + return SYNC_URL; +} + registerBidder(spec); diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index 36aaddb8b42..d972ec25c8a 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec } from 'modules/gridBidAdapter'; +import { spec, resetUserSync, getSyncUrl } from 'modules/gridBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; describe('TheMediaGrid Adapter', function () { @@ -577,4 +577,91 @@ describe('TheMediaGrid Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); }); + + describe('user sync', function () { + const syncUrl = getSyncUrl(); + + beforeEach(function () { + resetUserSync(); + }); + + it('should register the Emily iframe', function () { + let syncs = spec.getUserSyncs({ + pixelEnabled: true + }); + + expect(syncs).to.deep.equal({type: 'image', url: syncUrl}); + }); + + it('should not register the Emily iframe more than once', function () { + let syncs = spec.getUserSyncs({ + pixelEnabled: true + }); + expect(syncs).to.deep.equal({type: 'image', url: syncUrl}); + + // when called again, should still have only been called once + syncs = spec.getUserSyncs(); + expect(syncs).to.equal(undefined); + }); + + it('should pass gdpr params if consent is true', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { + gdprApplies: true, consentString: 'foo' + })).to.deep.equal({ + type: 'image', url: `${syncUrl}&gdpr=1&gdpr_consent=foo` + }); + }); + + it('should pass gdpr params if consent is false', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { + gdprApplies: false, consentString: 'foo' + })).to.deep.equal({ + type: 'image', url: `${syncUrl}&gdpr=0&gdpr_consent=foo` + }); + }); + + it('should pass gdpr param gdpr_consent only when gdprApplies is undefined', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { + consentString: 'foo' + })).to.deep.equal({ + type: 'image', url: `${syncUrl}&gdpr_consent=foo` + }); + }); + + it('should pass no params if gdpr consentString is not defined', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, {})).to.deep.equal({ + type: 'image', url: syncUrl + }); + }); + + it('should pass no params if gdpr consentString is a number', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { + consentString: 0 + })).to.deep.equal({ + type: 'image', url: syncUrl + }); + }); + + it('should pass no params if gdpr consentString is null', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { + consentString: null + })).to.deep.equal({ + type: 'image', url: syncUrl + }); + }); + + it('should pass no params if gdpr consentString is a object', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, { + consentString: {} + })).to.deep.equal({ + type: 'image', url: syncUrl + }); + }); + + it('should pass no params if gdpr is not defined', function () { + expect(spec.getUserSyncs({ pixelEnabled: true }, {}, undefined)).to.deep.equal({ + type: 'image', url: syncUrl + }); + }); + }); }); From c21af850a1f7745750b5474e2292911d8e3988b4 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Mon, 18 Nov 2019 08:52:29 -0800 Subject: [PATCH 410/436] Conversant Bid Adapter adds support for extended ids (#4462) --- modules/conversantBidAdapter.js | 45 +++++++++++++++++++ .../spec/modules/conversantBidAdapter_spec.js | 20 +++++++++ 2 files changed, 65 insertions(+) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index aa0761161f7..9ad1357fa2a 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -144,6 +144,12 @@ export const spec = { userExt.fpc = pubcid; } + // Add Eids if available + const eids = collectEids(validBidRequests); + if (eids.length > 0) { + userExt.eids = eids; + } + // Only add the user object if it's not empty if (!utils.isEmpty(userExt)) { payload.user = {ext: userExt}; @@ -294,6 +300,45 @@ function copyOptProperty(src, dst, dstName) { } } +/** + * Collect IDs from validBidRequests and store them as an extended id array + * @param bidRequests valid bid requests + */ +function collectEids(bidRequests) { + const request = bidRequests[0]; // bidRequests have the same userId object + const eids = []; + + addEid(eids, request, 'userId.tdid', 'adserver.org'); + addEid(eids, request, 'userId.idl_env', 'liveramp.com'); + addEid(eids, request, 'userId.criteoId', 'criteo.com'); + addEid(eids, request, 'userId.id5id', 'id5-sync.com'); + addEid(eids, request, 'userId.parrableid', 'parrable.com'); + addEid(eids, request, 'userId.digitrustid.data.id', 'digitru.st'); + addEid(eids, request, 'userId.lipb.lipbid', 'liveintent.com'); + + return eids; +} + +/** + * Extract and push a single extended id into eids array + * @param eids Array of extended IDs + * @param idObj Object containing IDs + * @param keyPath Nested properties expressed as a path + * @param source Source for the ID + */ +function addEid(eids, idObj, keyPath, source) { + const id = utils.deepAccess(idObj, keyPath); + if (id) { + eids.push({ + source: source, + uids: [{ + id: id, + atype: 1 + }] + }); + } +} + /** * Look for a stored value from both cookie and local storage and return the first value found. * @param key Key for the search diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 02a915f0c17..37a13312619 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -374,6 +374,7 @@ describe('Conversant adapter tests', function() { // construct http post payload const payload = spec.buildRequests(requests).data; expect(payload).to.have.deep.nested.property('user.ext.fpc', 12345); + expect(payload).to.not.have.nested.property('user.ext.eids'); }); it('Verify User ID publisher commond id support', function() { @@ -387,6 +388,7 @@ describe('Conversant adapter tests', function() { // construct http post payload const payload = spec.buildRequests(requests).data; expect(payload).to.have.deep.nested.property('user.ext.fpc', 67890); + expect(payload).to.not.have.nested.property('user.ext.eids'); }); it('Verify GDPR bid request', function() { @@ -416,6 +418,24 @@ describe('Conversant adapter tests', function() { expect(payload).to.not.have.deep.nested.property('regs.ext.gdpr'); }); + describe('Extended ID', function() { + it('Verify unifiedid and liveramp', function() { + // clone bidRequests + let requests = utils.deepClone(bidRequests); + + // add pubcid to every entry + requests.forEach((unit) => { + Object.assign(unit, {userId: {pubcid: 112233, tdid: 223344, idl_env: 334455}}); + }); + // construct http post payload + const payload = spec.buildRequests(requests).data; + expect(payload).to.have.deep.nested.property('user.ext.eids', [ + {source: 'adserver.org', uids: [{id: 223344, atype: 1}]}, + {source: 'liveramp.com', uids: [{id: 334455, atype: 1}]} + ]); + }); + }); + describe('direct reading pubcid', function() { const ID_NAME = '_pubcid'; const CUSTOM_ID_NAME = 'myid'; From 35a332eeb52d1849b215f4ff6e09977430e54b0a Mon Sep 17 00:00:00 2001 From: Denis Logachov Date: Mon, 18 Nov 2019 22:29:52 +0200 Subject: [PATCH 411/436] Adkernel 3.0 compatibility (#4477) --- modules/adkernelAdnBidAdapter.js | 2 +- modules/adkernelBidAdapter.js | 2 +- test/spec/modules/adkernelAdnBidAdapter_spec.js | 2 -- test/spec/modules/adkernelBidAdapter_spec.js | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 08842db37e3..3131aa2a38c 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -139,7 +139,7 @@ export const spec = { let request = buildRequestParams(dispatch[host][pubId], auctionId, transactionId, gdprConsent, refererInfo); requests.push({ method: 'POST', - url: `//${host}/tag?account=${pubId}&pb=1${isRtbDebugEnabled(refererInfo) ? '&debug=1' : ''}`, + url: `https://${host}/tag?account=${pubId}&pb=1${isRtbDebugEnabled(refererInfo) ? '&debug=1' : ''}`, data: JSON.stringify(request) }) }); diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index c406604b20e..7667212869b 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -43,7 +43,7 @@ export const spec = { const request = buildRtbRequest(impDispatch[host][zoneId], auctionId, gdprConsent, bidderRequest.refererInfo); requests.push({ method: 'POST', - url: `${window.location.protocol}//${host}/hb?zone=${zoneId}&v=${VERSION}`, + url: `https://${host}/hb?zone=${zoneId}&v=${VERSION}`, data: JSON.stringify(request) }); }); diff --git a/test/spec/modules/adkernelAdnBidAdapter_spec.js b/test/spec/modules/adkernelAdnBidAdapter_spec.js index 1147520131b..277faf2a351 100644 --- a/test/spec/modules/adkernelAdnBidAdapter_spec.js +++ b/test/spec/modules/adkernelAdnBidAdapter_spec.js @@ -74,7 +74,6 @@ describe('AdkernelAdn adapter', function () { bidderRequestId: 'req1', auctionId: '5c66da22-426a-4bac-b153-77360bef5337', bidId: 'bidid_5', - sizes: [[1920, 1080]], mediaTypes: { video: { playerSize: [1920, 1080], @@ -91,7 +90,6 @@ describe('AdkernelAdn adapter', function () { bidderRequestId: 'req-001', auctionId: 'auc-001', bidId: 'Bid_01', - sizes: [[300, 250], [300, 200]], mediaTypes: { banner: {sizes: [[300, 250], [300, 200]]}, video: {context: 'instream', playerSize: [[640, 480]]} diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index ddb3f3dddf2..317613224c3 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -81,7 +81,6 @@ describe('Adkernel adapter', function () { bidId: 'Bid_Video', bidderRequestId: '18b2a61ea5d9a7', auctionId: 'de45acf1-9109-4e52-8013-f2b7cf5f6766', - sizes: [[640, 480]], params: { zoneId: 1, host: 'rtb.adkernel.com', @@ -103,7 +102,6 @@ describe('Adkernel adapter', function () { }, adUnitCode: 'ad-unit-1', transactionId: 'f82c64b8-c602-42a4-9791-4a268f6559ed', - sizes: [[300, 250], [300, 200]], bidId: 'Bid_01', bidderRequestId: 'req-001', auctionId: 'auc-001' From 5a51011c0fe918cafc92eaebc89dcbeb528746a8 Mon Sep 17 00:00:00 2001 From: harpere Date: Mon, 18 Nov 2019 23:41:29 -0500 Subject: [PATCH 412/436] Rubicon Adapter pchain support (#4480) * rubicon pchain support * removed describe.only --- modules/rubiconBidAdapter.js | 2 ++ test/spec/modules/rubiconBidAdapter_spec.js | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 7e2b9147746..13d41978027 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -360,6 +360,7 @@ export const spec = { .concat([ 'tk_flint', 'x_source.tid', + 'x_source.pchain', 'p_screen_res', 'rp_floor', 'rp_secure', @@ -434,6 +435,7 @@ export const spec = { 'rp_secure': '1', 'tk_flint': `${configIntType || DEFAULT_INTEGRATION}_v$prebid.version$`, 'x_source.tid': bidRequest.transactionId, + 'x_source.pchain': params.pchain, 'p_screen_res': _getScreenResolution(), 'kw': Array.isArray(params.keywords) ? params.keywords.join(',') : '', 'tk_user_key': params.userId, diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 3de1418b65c..68abb7ffb77 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -279,6 +279,7 @@ describe('the rubicon adapter', function () { accountId: '14062', siteId: '70608', zoneId: '335918', + pchain: 'GAM:11111-reseller1:22222', userId: '12346', keywords: ['a', 'b', 'c'], inventory: { @@ -360,7 +361,7 @@ describe('the rubicon adapter', function () { describe('buildRequests implementation', function () { describe('for requests', function () { describe('to fastlane', function () { - it('should make a well-formed request objects', function () { + it('should make a well-formed request object', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -379,6 +380,7 @@ describe('the rubicon adapter', function () { 'rand': '0.1', 'tk_flint': INTEGRATION, 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.pchain': 'GAM:11111-reseller1:22222', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', 'kw': 'a,b,c', @@ -460,11 +462,20 @@ describe('the rubicon adapter', function () { expect(data['p_pos']).to.equal('atf;;btf;;'); }); + it('should not send x_source.pchain to AE if params.pchain is not specified', function() { + var noPchainRequest = utils.deepClone(bidderRequest); + delete noPchainRequest.bids[0].params.pchain; + + let [request] = spec.buildRequests(noPchainRequest.bids, noPchainRequest); + expect(request.data).to.contain('&site_id=70608&'); + expect(request.data).to.not.contain('x_source.pchain'); + }); + it('ad engine query params should be ordered correctly', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); - const referenceOrdering = ['account_id', 'site_id', 'zone_id', 'size_id', 'alt_size_ids', 'p_pos', 'rf', 'p_geo.latitude', 'p_geo.longitude', 'kw', 'tg_v.ucat', 'tg_v.lastsearch', 'tg_v.likes', 'tg_i.rating', 'tg_i.prodtype', 'tk_flint', 'x_source.tid', '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', 'x_source.pchain', '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]); From a9e9b6edf9baffbfde692984fb409417f166656d Mon Sep 17 00:00:00 2001 From: Index Exchange 3 Prebid Team Date: Tue, 19 Nov 2019 11:42:09 -0500 Subject: [PATCH 413/436] Implemented changes required to provide support for video in the IX bidding adapter for Instream and Outstream contexts. (#4424) --- modules/ixBidAdapter.js | 350 ++++++++++++++++--------- modules/ixBidAdapter.md | 130 ++++++++- test/spec/modules/ixBidAdapter_spec.js | 345 +++++++++++++++++++----- 3 files changed, 621 insertions(+), 204 deletions(-) diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 85d3be2f0ec..6ca5aaf1b65 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -1,36 +1,72 @@ import * as utils from '../src/utils'; -import { BANNER } from '../src/mediaTypes'; +import { BANNER, VIDEO } from '../src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; import { config } from '../src/config'; import 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 SUPPORTED_AD_TYPES = [BANNER]; -const ENDPOINT_VERSION = 7.2; +const SECURE_BID_URL = 'https://as-sec.casalemedia.com/cygnus'; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const BANNER_ENDPOINT_VERSION = 7.2; +const VIDEO_ENDPOINT_VERSION = 8.1; const CENT_TO_DOLLAR_FACTOR = 100; -const TIME_TO_LIVE = 35; +const BANNER_TIME_TO_LIVE = 35; +const VIDEO_TIME_TO_LIVE = 3600; // 1hr const NET_REVENUE = true; const PRICE_TO_DOLLAR_FACTOR = { JPY: 1 }; /** - * Transform valid bid request config object to impression object that will be sent to ad server. + * Transform valid bid request config object to banner impression object that will be sent to ad server. * * @param {object} bid A valid bid request config object. * @return {object} A impression object that will be sent to ad server. */ function bidToBannerImp(bid) { - const imp = {}; - - imp.id = bid.bidId; + const imp = bidToImp(bid); imp.banner = {}; imp.banner.w = bid.params.size[0]; imp.banner.h = bid.params.size[1]; imp.banner.topframe = utils.inIframe() ? 0 : 1; + return imp; +} + +/** + * Transform valid bid request config object to video impression object that will be sent to ad server. + * + * @param {object} bid A valid bid request config object. + * @return {object} A impression object that will be sent to ad server. + */ +function bidToVideoImp(bid) { + const imp = bidToImp(bid); + + imp.video = utils.deepClone(bid.params.video) + imp.video.w = bid.params.size[0]; + imp.video.h = bid.params.size[1]; + + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (context) { + if (context === 'instream') { + imp.video.placement = 1; + } else if (context === 'outstream') { + imp.video.placement = 4; + } else { + utils.logWarn(`ix bidder params: video context '${context}' is not supported`); + } + } + + return imp; +} + +function bidToImp(bid) { + const imp = {}; + + imp.id = bid.bidId; + imp.ext = {}; imp.ext.siteID = bid.params.siteId; @@ -56,7 +92,7 @@ function bidToBannerImp(bid) { * @param {string} currency Global currency in bid response. * @return {object} bid The parsed bid. */ -function parseBid(rawBid, currency) { +function parseBid(rawBid, currency, bidRequest) { const bid = {}; if (PRICE_TO_DOLLAR_FACTOR.hasOwnProperty(currency)) { @@ -66,15 +102,27 @@ function parseBid(rawBid, currency) { } bid.requestId = rawBid.impid; - bid.width = rawBid.w; - bid.height = rawBid.h; - bid.ad = rawBid.adm; + bid.dealId = utils.deepAccess(rawBid, 'ext.dealid'); - bid.ttl = TIME_TO_LIVE; bid.netRevenue = NET_REVENUE; bid.currency = currency; bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-'; + // in the event of a video + if (utils.deepAccess(rawBid, 'ext.vasturl')) { + bid.vastUrl = rawBid.ext.vasturl + bid.width = bidRequest.video.w; + bid.height = bidRequest.video.h; + bid.mediaType = VIDEO; + bid.ttl = VIDEO_TIME_TO_LIVE; + } else { + bid.ad = rawBid.adm; + bid.width = rawBid.w; + bid.height = rawBid.h; + bid.mediaType = BANNER; + bid.ttl = BANNER_TIME_TO_LIVE; + } + bid.meta = {}; bid.meta.networkId = utils.deepAccess(rawBid, 'ext.dspid'); bid.meta.brandId = utils.deepAccess(rawBid, 'ext.advbrandid'); @@ -131,6 +179,138 @@ function isValidBidFloorParams(bidFloor, bidFloorCur) { bidFloorCur.match(curRegex)); } +/** + * Finds the impression with the associated id. + * + * @param {*} id Id of the impression. + * @param {array} impressions List of impressions sent in the request. + * @return {object} The impression with the associated id. + */ +function getBidRequest(id, impressions) { + if (!id) { + return; + } + return find(impressions, imp => imp.id === id); +} + +/** + * Builds a request object to be sent to the ad server based on bid requests. + * + * @param {array} validBidRequests A list of valid bid request config objects. + * @param {object} bidderRequest An object containing other info like gdprConsent. + * @param {array} impressions List of impression objects describing the bids. + * @param {array} version Endpoint version denoting banner or video. + * @return {object} Info describing the request to the server. + * + */ +function buildRequest(validBidRequests, bidderRequest, impressions, version) { + const userEids = []; + + // Always use secure HTTPS protocol. + let baseUrl = SECURE_BID_URL; + + // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded + // and if the data for the partner exist + if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { + let identityInfo = window.headertag.getIdentityInfo(); + if (identityInfo && typeof identityInfo === 'object') { + for (const partnerName in identityInfo) { + if (identityInfo.hasOwnProperty(partnerName)) { + let response = identityInfo[partnerName]; + if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { + userEids.push(response.data); + } + } + } + } + } + const r = {}; + + // Since bidderRequestId are the same for different bid request, just use the first one. + r.id = validBidRequests[0].bidderRequestId; + + r.imp = impressions; + + r.site = {}; + r.ext = {}; + r.ext.source = 'prebid'; + if (userEids.length > 0) { + r.user = {}; + r.user.eids = userEids; + } + + if (document.referrer && document.referrer !== '') { + r.site.ref = document.referrer; + } + + // Apply GDPR information to the request if GDPR is enabled. + if (bidderRequest) { + if (bidderRequest.gdprConsent) { + const gdprConsent = bidderRequest.gdprConsent; + + if (gdprConsent.hasOwnProperty('gdprApplies')) { + r.regs = { + ext: { + gdpr: gdprConsent.gdprApplies ? 1 : 0 + } + }; + } + + if (gdprConsent.hasOwnProperty('consentString')) { + r.user = r.user || {}; + r.user.ext = { + consent: gdprConsent.consentString || '' + }; + } + } + + if (bidderRequest.refererInfo) { + r.site.page = bidderRequest.refererInfo.referer; + } + } + + const payload = {}; + + // Parse additional runtime configs. + const otherIxConfig = config.getConfig('ix'); + if (otherIxConfig) { + // Append firstPartyData to r.site.page if firstPartyData exists. + if (typeof otherIxConfig.firstPartyData === 'object') { + const firstPartyData = otherIxConfig.firstPartyData; + let firstPartyString = '?'; + for (const key in firstPartyData) { + if (firstPartyData.hasOwnProperty(key)) { + firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; + } + } + firstPartyString = firstPartyString.slice(0, -1); + + r.site.page += firstPartyString; + } + + // Create t in payload if timeout is configured. + if (typeof otherIxConfig.timeout === 'number') { + payload.t = otherIxConfig.timeout; + } + } + + // Use the siteId in the first bid request as the main siteId. + payload.s = validBidRequests[0].params.siteId; + payload.v = version; + payload.r = JSON.stringify(r); + payload.ac = 'j'; + payload.sd = 1; + if (version === VIDEO_ENDPOINT_VERSION) { + payload.nf = 1; + } + + return { + method: 'GET', + url: baseUrl, + data: payload + }; +} + export const spec = { code: BIDDER_CODE, @@ -144,22 +324,25 @@ export const spec = { */ isBidRequestValid: function (bid) { if (!isValidSize(bid.params.size)) { + utils.logError('ix bidder params: bid size has invalid format.'); return false; } if (!includesSize(bid.sizes, bid.params.size)) { + utils.logError('ix bidder params: bid size is not included in ad unit sizes.'); return false; } - if (bid.hasOwnProperty('mediaType') && bid.mediaType !== 'banner') { + if (bid.hasOwnProperty('mediaType') && !(utils.contains(SUPPORTED_AD_TYPES, bid.mediaType))) { return false; } - if (bid.hasOwnProperty('mediaTypes') && !utils.deepAccess(bid, 'mediaTypes.banner.sizes')) { + if (bid.hasOwnProperty('mediaTypes') && !(utils.deepAccess(bid, 'mediaTypes.banner.sizes') || utils.deepAccess(bid, 'mediaTypes.video.playerSize'))) { return false; } if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') { + utils.logError('ix bidder params: siteId must be string or number value.'); return false; } @@ -167,8 +350,10 @@ export const spec = { const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur'); if (hasBidFloor || hasBidFloorCur) { - return hasBidFloor && hasBidFloorCur && - isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur); + if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) { + utils.logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.'); + return false; + } } return true; @@ -178,132 +363,50 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {array} validBidRequests A list of valid bid request config objects. - * @param {object} options A object contains bids and other info like gdprConsent. + * @param {object} bidderRequest A object contains bids and other info like gdprConsent. * @return {object} Info describing the request to the server. */ - buildRequests: function (validBidRequests, options) { - const bannerImps = []; - const userEids = []; + buildRequests: function (validBidRequests, bidderRequest) { + let reqs = []; + let bannerImps = []; + let videoImps = []; let validBidRequest = null; - let bannerImp = null; - - // Always use secure HTTPS protocol. - let baseUrl = BANNER_SECURE_BID_URL; for (let i = 0; i < validBidRequests.length; i++) { validBidRequest = validBidRequests[i]; - // Transform the bid request based on the banner format. - bannerImp = bidToBannerImp(validBidRequest); - bannerImps.push(bannerImp); - } - - // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded - // and if the data for the partner exist - if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') { - let identityInfo = window.headertag.getIdentityInfo(); - if (identityInfo && typeof identityInfo === 'object') { - for (const partnerName in identityInfo) { - if (identityInfo.hasOwnProperty(partnerName)) { - let response = identityInfo[partnerName]; - if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) { - userEids.push(response.data); - } - } + if (validBidRequest.mediaType === VIDEO || utils.deepAccess(validBidRequest, 'mediaTypes.video')) { + if (validBidRequest.mediaType === VIDEO || includesSize(validBidRequest.mediaTypes.video.playerSize, validBidRequest.params.size)) { + videoImps.push(bidToVideoImp(validBidRequest)); + } else { + utils.logError('Bid size is not included in video playerSize') } } - } - const r = {}; - - // Since bidderRequestId are the same for different bid request, just use the first one. - r.id = validBidRequests[0].bidderRequestId; - - r.imp = bannerImps; - r.site = {}; - r.ext = {}; - r.ext.source = 'prebid'; - if (userEids.length > 0) { - r.user = {}; - r.user.eids = userEids; - } - if (document.referrer && document.referrer !== '') { - r.site.ref = document.referrer; - } - - // Apply GDPR information to the request if GDPR is enabled. - if (options) { - if (options.gdprConsent) { - const gdprConsent = options.gdprConsent; - - if (gdprConsent.hasOwnProperty('gdprApplies')) { - r.regs = { - ext: { - gdpr: gdprConsent.gdprApplies ? 1 : 0 - } - }; - } - - if (gdprConsent.hasOwnProperty('consentString')) { - r.user = r.user || {}; - r.user.ext = { - consent: gdprConsent.consentString || '' - }; - } - } - - if (options.refererInfo) { - r.site.page = options.refererInfo.referer; + if (validBidRequest.mediaType === BANNER || utils.deepAccess(validBidRequest, 'mediaTypes.banner') || + (!validBidRequest.mediaType && !validBidRequest.mediaTypes)) { + bannerImps.push(bidToBannerImp(validBidRequest)); } } - const payload = {}; - - // Parse additional runtime configs. - const otherIxConfig = config.getConfig('ix'); - if (otherIxConfig) { - // Append firstPartyData to r.site.page if firstPartyData exists. - if (typeof otherIxConfig.firstPartyData === 'object') { - const firstPartyData = otherIxConfig.firstPartyData; - let firstPartyString = '?'; - for (const key in firstPartyData) { - if (firstPartyData.hasOwnProperty(key)) { - firstPartyString += `${encodeURIComponent(key)}=${encodeURIComponent(firstPartyData[key])}&`; - } - } - firstPartyString = firstPartyString.slice(0, -1); - - r.site.page += firstPartyString; - } - - // Create t in payload if timeout is configured. - if (typeof otherIxConfig.timeout === 'number') { - payload.t = otherIxConfig.timeout; - } + if (bannerImps.length > 0) { + reqs.push(buildRequest(validBidRequests, bidderRequest, bannerImps, BANNER_ENDPOINT_VERSION)); + } + if (videoImps.length > 0) { + reqs.push(buildRequest(validBidRequests, bidderRequest, videoImps, VIDEO_ENDPOINT_VERSION)); } - // Use the siteId in the first bid request as the main siteId. - payload.s = validBidRequests[0].params.siteId; - - payload.v = ENDPOINT_VERSION; - payload.r = JSON.stringify(r); - payload.ac = 'j'; - payload.sd = 1; - - return { - method: 'GET', - url: baseUrl, - data: payload - }; + return reqs; }, /** * Unpack the response from the server into a list of bids. * * @param {object} serverResponse A successful response from the server. + * @param {object} bidderRequest The bid request sent to the server. * @return {array} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse) { + interpretResponse: function (serverResponse, bidderRequest) { const bids = []; let bid = null; @@ -320,8 +423,11 @@ export const spec = { // Transform rawBid in bid response to the format that will be accepted by prebid. const innerBids = seatbid[i].bid; + let requestBid = JSON.parse(bidderRequest.data.r); + for (let j = 0; j < innerBids.length; j++) { - bid = parseBid(innerBids[j], responseBody.cur); + const bidRequest = getBidRequest(innerBids[j].impid, requestBid.imp); + bid = parseBid(innerBids[j], responseBody.cur, bidRequest); bids.push(bid); } } diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md index e99c42408f2..d343b007c5b 100644 --- a/modules/ixBidAdapter.md +++ b/modules/ixBidAdapter.md @@ -42,16 +42,21 @@ var adUnits = [{ ```javascript var adUnits = [{ // ... - mediaTypes: { banner: { sizes: [ [300, 250], [300, 600] ] + }, + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] } - } - + }, // ... }]; ``` @@ -61,7 +66,7 @@ var adUnits = [{ | Type | Support | --- | --- | Banner | Fully supported for all IX approved sizes. -| Video | Not supported. +| Video | Fully supported for all IX approved sizes. | Native | Not supported. # Bid Parameters @@ -76,6 +81,17 @@ object are detailed here. | siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` | size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`. Examples: `[300, 250]`, `[300, 600]`, `[728, 90]` +### Video + +| Key | Scope | Type | Description +| --- | --- | --- | --- +| siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'` +| size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.video.playerSize`. Examples: `[300, 250]`, `[300, 600]` +| video | Required | Hash | The video object will serve as the properties of the video ad. You can create any field under the video object that is mentioned in the `OpenRTB Spec v2.5`. Some fields like `mimes, protocols, minduration, maxduration` are required. +| video.mimes | Required | String[] | Array list of content MIME types supported. Popular MIME types include, but are not limited to, `"video/x-ms- wmv"` for Windows Media and `"video/x-flv"` for Flash Video. +|video.minduration| Required | Integer | Minimum video ad duration in seconds. +|video.maxduration| Required | Integer | Maximum video ad duration in seconds. +|video.protocol / video.protocols| Required | Integer / Integer[] | Either a single protocol provided as an integer, or protocols provided as a list of integers. `2` - VAST 2.0, `3` - VAST 3.0, `5` - VAST 2.0 Wrapper, `6` - VAST 3.0 Wrapper Setup Guide @@ -84,7 +100,9 @@ Setup Guide Follow these steps to configure and add the IX module to your Prebid.js integration. -The examples in this guide assume the following starting configuration: +The examples in this guide assume the following starting configuration (you may remove banner or video, if either does not apply). + +In regards to video, `context` can either be `'instream'` or `'outstream'`. Note that `outstream` requires additional configuration on the adUnit. ```javascript var adUnits = [{ @@ -98,6 +116,19 @@ var adUnits = [{ } }, bids: [] +}, +{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [] }]; ``` @@ -119,7 +150,9 @@ bid objects under `adUnits[].bids`: Set `params.siteId` and `params.size` in each bid object to the values provided by your IX representative. -**Example** +**Examples** + +**Banner:** ```javascript var adUnits = [{ code: 'banner-div-a', @@ -146,18 +179,92 @@ var adUnits = [{ }] }]; ``` - +**Video (Instream):** +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'instream', + playerSize: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 250], + video: { + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0, + maxduration: 60, + protocols: [6] + } + } + }, { + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 600], + video: { + // openrtb v2.5 compatible video obj + } + } + }] +}]; +``` Please note that you can re-use the existing `siteId` within the same flex position. +**Video (Outstream):** +Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See http://prebid.org/dev-docs/show-outstream-video-ads.html for more information. +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[300, 250]] + } + }, + renderer: { + url: 'https://test.com/my-video-player.js', + render: function (bid) { + ... + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '12345', + size: [300, 250], + video: { + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0, + maxduration: 60, + protocols: [6] + } + } + }] +}]; +``` ##### 2. Include `ixBidAdapter` in your build process -When running the build command, include `ixBidAdapter` as a module. +When running the build command, include `ixBidAdapter` as a module, as well as `dfpAdServerVideo` if you require video support. ``` -gulp build --modules=ixBidAdapter,fooBidAdapter,bazBidAdapter +gulp build --modules=ixBidAdapter,dfpAdServerVideo,fooBidAdapter,bazBidAdapter ``` If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` @@ -166,6 +273,7 @@ to the top-level array in that file. ```json [ "ixBidAdapter", + "dfpAdServerVideo", "fooBidAdapter", "bazBidAdapter" ] @@ -210,9 +318,7 @@ 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. +Setting a server-side timeout allows you to control the max length of time taken to connect to the server. The default value when unspecified is 50ms. This is distinctly different from the global bidder timeout that can be set in Prebid.js in the browser. diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 120d02408d7..245cf01610c 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -6,7 +6,8 @@ import { spec } from 'modules/ixBidAdapter'; describe('IndexexchangeAdapter', function () { const IX_SECURE_ENDPOINT = 'https://as-sec.casalemedia.com/cygnus'; - const BIDDER_VERSION = 7.2; + const VIDEO_ENDPOINT_VERSION = 8.1; + const BANNER_ENDPOINT_VERSION = 7.2; const DEFAULT_BANNER_VALID_BID = [ { @@ -28,17 +29,37 @@ describe('IndexexchangeAdapter', function () { auctionId: '1aa2bb3cc4dd' } ]; - const DEFAULT_BANNER_OPTION = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - referer: 'http://www.prebid.org', - canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + + const DEFAULT_VIDEO_VALID_BID = [ + { + bidder: 'ix', + params: { + siteId: '456', + video: { + skippable: false, + mimes: [ + 'video/mp4', + 'video/webm' + ], + minduration: 0 + }, + size: [400, 100] + }, + sizes: [[400, 100], [200, 400]], + mediaTypes: { + video: { + context: 'instream', + playerSize: [[400, 100], [200, 400]] + } + }, + adUnitCode: 'div-gpt-ad-1460505748562-0', + transactionId: '173f49a8-7549-4218-a23c-e7ba59b47230', + bidId: '1a2b3c4e', + bidderRequestId: '11a22b33c44e', + auctionId: '1aa2bb3cc4de' } - }; + ]; + const DEFAULT_BANNER_BID_RESPONSE = { cur: 'USD', id: '11a22b33c44d', @@ -68,6 +89,48 @@ describe('IndexexchangeAdapter', function () { } ] }; + + const DEFAULT_VIDEO_BID_RESPONSE = { + cur: 'USD', + id: '1aa2bb3cc4de', + seatbid: [ + { + bid: [ + { + crid: '12346', + adomain: ['www.abcd.com'], + adid: '14851456', + impid: '1a2b3c4e', + cid: '3051267', + price: 110, + id: '2', + ext: { + vasturl: 'www.abcd.com/vast', + errorurl: 'www.abcd.com/error', + dspid: 51, + pricelevel: '_110', + advbrandid: 303326, + advbrand: 'OECTB' + } + } + ], + seat: '3971' + } + ] + }; + + const DEFAULT_OPTION = { + gdprConsent: { + gdprApplies: true, + consentString: '3huaa11=qu3198ae', + vendorData: {} + }, + refererInfo: { + referer: 'http://www.prebid.org', + canonicalUrl: 'http://www.prebid.org/the/link/to/the/page' + } + }; + const DEFAULT_IDENTITY_RESPONSE = { IdentityIp: { responsePending: false, @@ -82,6 +145,31 @@ describe('IndexexchangeAdapter', function () { } }; + const DEFAULT_BIDDER_REQUEST_DATA = { + ac: 'j', + r: JSON.stringify({ + id: '345', + imp: [ + { + id: '1a2b3c4e', + video: { + w: 640, + h: 480, + placement: 1 + } + } + ], + site: { + ref: 'http://ref.com/ref.html', + page: 'http://page.com' + }, + }), + s: '21', + sd: 1, + t: 1000, + v: 8.1 + }; + describe('inherited functions', function () { it('should exists and is a function', function () { const adapter = newBidder(spec); @@ -90,11 +178,12 @@ describe('IndexexchangeAdapter', function () { }); describe('isBidRequestValid', function () { - it('should return true when required params found for a banner ad', function () { + it('should return true when required params found for a banner or video ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); + expect(spec.isBidRequestValid(DEFAULT_VIDEO_VALID_BID[0])).to.equal(true); }); - it('should return true when optional params found for a banner ad', function () { + it('should return true when optional bidFloor params found for an ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -135,10 +224,10 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaTypes is not banner', function () { + it('should return false when mediaTypes is not banner or video', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.mediaTypes = { - video: { + native: { sizes: [[300, 250]] } }; @@ -155,19 +244,13 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when mediaType is not banner', function () { - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - delete bid.params.mediaTypes; - bid.mediaType = 'banne'; - bid.sizes = [[300, 250]]; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should return false when mediaType is video', function () { - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - delete bid.params.mediaTypes; - bid.mediaType = 'video'; - bid.sizes = [[300, 250]]; + it('should return false when mediaTypes.video does not have sizes', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + bid.mediaTypes = { + video: { + size: [[300, 250]] + } + }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -194,6 +277,14 @@ describe('IndexexchangeAdapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); + it('should return true when mediaType is video', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'video'; + bid.sizes = [[400, 100]]; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; @@ -231,7 +322,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return testCopy; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; }); afterEach(function() { @@ -342,7 +433,7 @@ describe('IndexexchangeAdapter', function () { window.headertag.getIdentityInfo = function() { return undefined; }; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -355,7 +446,7 @@ describe('IndexexchangeAdapter', function () { responsePending: true, data: {} } - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -365,7 +456,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending for all partners', function () { testCopy.IdentityIp.responsePending = true; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -376,7 +467,7 @@ describe('IndexexchangeAdapter', function () { it('payload should not have any user eids if identity data is pending or not available for all partners', function () { testCopy.IdentityIp.responsePending = false; testCopy.IdentityIp.data = {}; - request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; query = request.data; const payload = JSON.parse(query.r); @@ -386,8 +477,8 @@ describe('IndexexchangeAdapter', function () { }); }); - describe('buildRequestsBanner', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + describe('buildRequests', function () { + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const requestUrl = request.url; const requestMethod = request.method; const query = request.data; @@ -395,7 +486,7 @@ describe('IndexexchangeAdapter', function () { const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); delete bidWithoutMediaType[0].mediaTypes; bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; - const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_BANNER_OPTION); + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType, DEFAULT_OPTION)[0]; const queryWithoutMediaType = requestWithoutMediaType.data; it('request should be made to IX endpoint with GET method', function () { @@ -404,11 +495,12 @@ describe('IndexexchangeAdapter', function () { }); it('query object (version, siteID and request) should be correct', function () { - expect(query.v).to.equal(BIDDER_VERSION); + expect(query.v).to.equal(BANNER_ENDPOINT_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; expect(query.ac).to.equal('j'); expect(query.sd).to.equal(1); + expect(query.nf).not.to.exist; }); it('payload should have correct format and value', function () { @@ -416,7 +508,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -444,7 +536,7 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.bidfloor).to.equal(bid.params.bidFloor); @@ -456,7 +548,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); expect(payload.site).to.exist; - expect(payload.site.page).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(payload.site.page).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(payload.site.ref).to.equal(document.referrer); expect(payload.ext).to.exist; expect(payload.ext.source).to.equal('prebid'); @@ -483,7 +575,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 50; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); @@ -500,7 +592,7 @@ describe('IndexexchangeAdapter', function () { it('impression should have sid if id is configured as string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.id = 'abc'; - const requestBidFloor = spec.buildRequests([bid]); + const requestBidFloor = spec.buildRequests([bid])[0]; const impression = JSON.parse(requestBidFloor.data.r).imp[0]; expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); expect(impression.banner).to.exist; @@ -525,9 +617,9 @@ describe('IndexexchangeAdapter', function () { } }); - const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; - const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; + const expectedPageUrl = DEFAULT_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); }); @@ -539,10 +631,10 @@ describe('IndexexchangeAdapter', function () { } }); - const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestFirstPartyDataNumber = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestFirstPartyDataNumber.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); }); it('should not set first party or timeout if it is not present', function () { @@ -550,18 +642,18 @@ describe('IndexexchangeAdapter', function () { ix: {} }); - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); it('should not set first party or timeout if it is setConfig is not called', function () { - const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); + const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION)[0]; const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; - expect(pageUrl).to.equal(DEFAULT_BANNER_OPTION.refererInfo.referer); + expect(pageUrl).to.equal(DEFAULT_OPTION.refererInfo.referer); expect(requestWithoutConfig.data.t).to.be.undefined; }); @@ -571,7 +663,7 @@ describe('IndexexchangeAdapter', function () { timeout: 500 } }); - const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestWithTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; expect(requestWithTimeout.data.t).to.equal(500); }); @@ -582,14 +674,99 @@ describe('IndexexchangeAdapter', function () { timeout: '500' } }); - const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID); + const requestStringTimeout = spec.buildRequests(DEFAULT_BANNER_VALID_BID)[0]; expect(requestStringTimeout.data.t).to.be.undefined; }); + + it('request should contain both banner and video requests', function () { + const request = spec.buildRequests([DEFAULT_BANNER_VALID_BID[0], DEFAULT_VIDEO_VALID_BID[0]]); + + const bannerImp = JSON.parse(request[0].data.r).imp[0]; + expect(JSON.parse(request[0].data.v)).to.equal(BANNER_ENDPOINT_VERSION); + expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(bannerImp.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(bannerImp.banner).to.exist; + expect(bannerImp.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(bannerImp.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + + const videoImp = JSON.parse(request[1].data.r).imp[0]; + expect(JSON.parse(request[1].data.v)).to.equal(VIDEO_ENDPOINT_VERSION); + expect(videoImp.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(videoImp.video).to.exist; + expect(videoImp.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(videoImp.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + }); }); - describe('interpretResponseBanner', function () { - it('should get correct bid response', function () { + describe('buildRequestVideo', function () { + const request = spec.buildRequests(DEFAULT_VIDEO_VALID_BID, DEFAULT_OPTION); + const query = request[0].data; + + it('query object (version, siteID and request) should be correct', function () { + expect(query.v).to.equal(VIDEO_ENDPOINT_VERSION); + expect(query.s).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId); + expect(query.r).to.exist; + expect(query.ac).to.equal('j'); + expect(query.sd).to.equal(1); + expect(query.nf).to.equal(1); + }); + + it('impression should have correct format and value', function () { + const impression = JSON.parse(query.r).imp[0]; + const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + expect(impression.video.placement).to.exist; + expect(impression.video.placement).to.equal(1); + expect(impression.video.minduration).to.exist; + expect(impression.video.minduration).to.equal(0); + expect(impression.video.mimes).to.exist; + expect(impression.video.mimes[0]).to.equal('video/mp4'); + expect(impression.video.mimes[1]).to.equal('video/webm'); + + expect(impression.video.skippable).to.equal(false); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('impression should have correct format when mediaType is specified.', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'video'; + const requestBidFloor = spec.buildRequests([bid])[0]; + const impression = JSON.parse(requestBidFloor.data.r).imp[0]; + const sidValue = `${DEFAULT_VIDEO_VALID_BID[0].params.size[0].toString()}x${DEFAULT_VIDEO_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.w).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[0]); + expect(impression.video.h).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.size[1]); + expect(impression.video.placement).to.not.exist; + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_VIDEO_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('should set correct placement if context is outstream', function () { + const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID[0]); + bid.mediaTypes.video.context = 'outstream'; + const request = spec.buildRequests([bid])[0]; + const impression = JSON.parse(request.data.r).imp[0]; + + expect(impression.id).to.equal(DEFAULT_VIDEO_VALID_BID[0].bidId); + expect(impression.video).to.exist; + expect(impression.video.placement).to.exist; + expect(impression.video.placement).to.equal(4); + }); + }); + + describe('interpretResponse', function () { + it('should get correct bid response for banner ad', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -597,6 +774,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -609,7 +787,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }); + const result = spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -623,6 +801,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '-', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -635,8 +814,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); - expect(result[0]).to.deep.equal(expectedParse[0]); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); }); it('should set Japanese price correctly', function () { @@ -649,6 +827,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'JPY', ttl: 35, @@ -661,7 +840,7 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); @@ -675,6 +854,7 @@ describe('IndexexchangeAdapter', function () { creativeId: '12345', width: 300, height: 250, + mediaType: 'banner', ad: '', currency: 'USD', ttl: 35, @@ -687,13 +867,38 @@ describe('IndexexchangeAdapter', function () { } } ]; - const result = spec.interpretResponse({ body: bidResponse }); + const result = spec.interpretResponse({ body: bidResponse }, { data: DEFAULT_BIDDER_REQUEST_DATA }); + expect(result[0]).to.deep.equal(expectedParse[0]); + }); + + it('should get correct bid response for video ad', function () { + const expectedParse = [ + { + requestId: '1a2b3c4e', + cpm: 1.1, + creativeId: '12346', + mediaType: 'video', + width: 640, + height: 480, + currency: 'USD', + ttl: 3600, + netRevenue: true, + dealId: undefined, + vastUrl: 'www.abcd.com/vast', + meta: { + networkId: 51, + brandId: 303326, + brandName: 'OECTB' + } + } + ]; + const result = spec.interpretResponse({ body: DEFAULT_VIDEO_BID_RESPONSE }, { data: DEFAULT_BIDDER_REQUEST_DATA }); expect(result[0]).to.deep.equal(expectedParse[0]); }); it('bidrequest should have consent info if gdprApplies and consentString exist', function () { - const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -707,7 +912,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs.ext.gdpr).to.equal(1); expect(requestWithConsent.user).to.be.undefined; @@ -721,7 +926,7 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); @@ -730,7 +935,7 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithConsent = JSON.parse(validBidWithConsent.data.r); + const requestWithConsent = JSON.parse(validBidWithConsent[0].data.r); expect(requestWithConsent.regs).to.be.undefined; expect(requestWithConsent.user).to.be.undefined; @@ -739,10 +944,10 @@ describe('IndexexchangeAdapter', function () { it('bidrequest should not have page if options is undefined', function () { const options = {}; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should not have page if options.refererInfo is an empty object', function () { @@ -750,10 +955,10 @@ describe('IndexexchangeAdapter', function () { refererInfo: {} }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.be.undefined; - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); it('bidrequest should sent to secure endpoint if page url is secure', function () { @@ -763,10 +968,10 @@ describe('IndexexchangeAdapter', function () { } }; const validBidWithoutreferInfo = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); - const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo.data.r); + const requestWithoutreferInfo = JSON.parse(validBidWithoutreferInfo[0].data.r); expect(requestWithoutreferInfo.site.page).to.equal(options.refererInfo.referer); - expect(validBidWithoutreferInfo.url).to.equal(IX_SECURE_ENDPOINT); + expect(validBidWithoutreferInfo[0].url).to.equal(IX_SECURE_ENDPOINT); }); }); }); From 4904963b13e5962debd9d69867a77fa27bf89068 Mon Sep 17 00:00:00 2001 From: Steve Alliance Date: Tue, 19 Nov 2019 15:03:31 -0500 Subject: [PATCH 414/436] Default size filter & KVP support (#4452) * adding DMX test @97%, two files added one updated * Update districtm_spec.js * Update districtmDMX.js * adding all districtm needed file * remove legacy file * remove typo || 0 in the test method * force default to return a valid width and height * update unit test code for failing test * changed class for an object * remove package-lock.json * change file name for dmx adapter * renamed files * restaure package-lock.json * update to last package-lock state * update gdpr user consent * fix sizes issue * Documentation updates Adding the readme.md info * update file name and update unit testing import file location * current machine state * lint correction * remove variable assigment duplicate * adding logic upto5 * adding support for removing and shuffle sizes * adding array split test * re-assign none standard size to the request * resolve duplicate format inside format array * update .md and adaptor file for KVP support * remove array helper includes * inforce two digit after decimal * RUn error check nothing on my side but error form another adapter --- modules/districtmDMXBidAdapter.js | 128 ++++++++++++++++-- modules/districtmDmxBidAdapter.md | 22 +++ .../modules/districtmDmxBidAdapter_spec.js | 42 +++++- 3 files changed, 180 insertions(+), 12 deletions(-) diff --git a/modules/districtmDMXBidAdapter.js b/modules/districtmDMXBidAdapter.js index 5942e0ea683..205017066a8 100644 --- a/modules/districtmDMXBidAdapter.js +++ b/modules/districtmDMXBidAdapter.js @@ -22,7 +22,7 @@ export const spec = { if (oBid.price < nBid.price) { const bid = matchRequest(nBid.impid, bidRequest); const {width, height} = defaultSize(bid); - nBid.cpm = nBid.price; + nBid.cpm = parseFloat(nBid.price).toFixed(2); nBid.bidId = nBid.impid; nBid.requestId = nBid.impid; nBid.width = nBid.w || width; @@ -32,7 +32,6 @@ export const spec = { nBid.creativeId = nBid.crid; nBid.currency = 'USD'; nBid.ttl = 60; - return nBid; } else { oBid.cpm = oBid.price; @@ -69,6 +68,14 @@ export const spec = { site: { publisher: { id: String(bidRequest[0].params.memberid) || null } } + } + try { + let params = config.getConfig('dmx'); + dmxRequest.user = params.user || {}; + let site = params.site || {}; + dmxRequest.site = {...dmxRequest.site, ...site} + } catch (e) { + } if (!dmxRequest.test) { delete dmxRequest.test; @@ -94,21 +101,25 @@ export const spec = { obj.secure = 1; obj.banner = { topframe: 1, - w: dmx.sizes[0][0] || 0, - h: dmx.sizes[0][1] || 0, - format: dmx.sizes.map(s => { + w: cleanSizes(dmx.sizes, 'w'), + h: cleanSizes(dmx.sizes, 'h'), + format: cleanSizes(dmx.sizes).map(s => { return {w: s[0], h: s[1]}; }).filter(obj => typeof obj.w === 'number' && typeof obj.h === 'number') }; return obj; }); - dmxRequest.imp = tosendtags; - return { - method: 'POST', - url: DMXURI, - data: JSON.stringify(dmxRequest), - bidderRequest + if (tosendtags.length <= 5) { + dmxRequest.imp = tosendtags; + return { + method: 'POST', + url: DMXURI, + data: JSON.stringify(dmxRequest), + bidderRequest + } + } else { + return upto5(tosendtags, dmxRequest, bidderRequest, DMXURI); } }, test() { @@ -124,6 +135,101 @@ export const spec = { } } +export function cleanSizes(sizes, value) { + const supportedSize = [ + { + size: [300, 250], + s: 100 + }, + { + size: [728, 90], + s: 95 + }, + { + size: [320, 50], + s: 90 + }, + { + size: [160, 600], + s: 88 + }, + { + size: [300, 600], + s: 85 + }, + { + size: [300, 50], + s: 80 + }, + { + size: [970, 250], + s: 75 + }, + { + size: [970, 90], + s: 60 + }, + ]; + let newArray = shuffle(sizes, supportedSize); + switch (value) { + case 'w': + return newArray[0][0] || 0; + case 'h': + return newArray[0][1] || 0; + case 'size': + return newArray; + default: + return newArray; + } +} + +export function shuffle(sizes, list) { + let removeSizes = sizes.filter(size => { + return list.map(l => `${l.size[0]}x${l.size[1]}`).indexOf(`${size[0]}x${size[1]}`) === -1 + }) + let reOrder = sizes.reduce((results, current) => { + if (results.length === 0) { + results.push(current); + return results; + } + results.push(current); + results = list.filter(l => results.map(r => `${r[0]}x${r[1]}`).indexOf(`${l.size[0]}x${l.size[1]}`) !== -1); + results = results.sort(function(a, b) { + return b.s - a.s; + }) + return results.map(r => r.size); + }, []) + return removeDuplicate([...reOrder, ...removeSizes]); +} + +export function removeDuplicate(arrayValue) { + return arrayValue.filter((elem, index) => { + return arrayValue.map(e => `${e[0]}x${e[1]}`).indexOf(`${elem[0]}x${elem[1]}`) === index + }) +} + +export function upto5(allimps, dmxRequest, bidderRequest, DMXURI) { + let start = 0; + let step = 5; + let req = []; + while (allimps.length !== 0) { + if (allimps.length >= 5) { + req.push(allimps.splice(start, step)) + } else { + req.push(allimps.splice(start, allimps.length)) + } + } + return req.map(r => { + dmxRequest.imp = r; + return { + method: 'POST', + url: DMXURI, + data: JSON.stringify(dmxRequest), + bidderRequest + } + }) +} + /** * Function matchRequest(id: string, BidRequest: object) * @param id diff --git a/modules/districtmDmxBidAdapter.md b/modules/districtmDmxBidAdapter.md index 2859bcfa19d..5bc1e5d5780 100644 --- a/modules/districtmDmxBidAdapter.md +++ b/modules/districtmDmxBidAdapter.md @@ -115,3 +115,25 @@ Our demand and adapter supports multiple sizes per placement, as such a single d ###### 4. Implementation Checking Once the bidder is live in your Prebid configuration you may confirm it is making requests to our end point by looking for requests to `https://dmx.districtm.io/b/v1`. + + +###### 5. Setting first party data + +```code +pbjs.setConfig({ + dmx: { + user: { + 'gender': 'M', + 'yob': 1992, + // keywords example + 'keywords': 'automotive,dodge,engine,car' + + }, + site: { + cat: ['IAB-12'], + pagecat: ['IAB-14'], + sectioncat: ['IAB-24'] + } + } +}); +``` diff --git a/test/spec/modules/districtmDmxBidAdapter_spec.js b/test/spec/modules/districtmDmxBidAdapter_spec.js index 64f76eb026d..ac8698f63a9 100644 --- a/test/spec/modules/districtmDmxBidAdapter_spec.js +++ b/test/spec/modules/districtmDmxBidAdapter_spec.js @@ -1,7 +1,41 @@ import {expect} from 'chai'; import * as _ from 'lodash'; -import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDMXBidAdapter'; +import {spec, matchRequest, checkDeepArray, defaultSize, upto5, cleanSizes, shuffle} from '../../../modules/districtmDMXBidAdapter'; +const supportedSize = [ + { + size: [300, 250], + s: 100 + }, + { + size: [728, 90], + s: 95 + }, + { + size: [300, 600], + s: 90 + }, + { + size: [160, 600], + s: 88 + }, + { + size: [320, 50], + s: 85 + }, + { + size: [300, 50], + s: 80 + }, + { + size: [970, 250], + s: 75 + }, + { + size: [970, 90], + s: 60 + }, +]; const bidRequest = [{ 'bidder': 'districtmDMX', 'params': { @@ -422,6 +456,12 @@ const emptyResponseSeatBid = { body: { seatbid: [] } }; describe('DistrictM Adaptor', function () { const districtm = spec; + describe('verification of upto5', function() { + it('upto5 function should always break 12 imps into 3 request same for 15', function() { + expect(upto5([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], bidRequest, bidderRequest, 'https://google').length).to.be.equal(3) + expect(upto5([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], bidRequest, bidderRequest, 'https://google').length).to.be.equal(3) + }) + }) describe('All needed functions are available', function () { it(`isBidRequestValid is present and type function`, function () { expect(districtm.isBidRequestValid).to.exist.and.to.be.a('function') From 8f453cfcedaddcdb70ac4b6385d619881fc297f7 Mon Sep 17 00:00:00 2001 From: Scott Date: Tue, 19 Nov 2019 21:22:59 +0100 Subject: [PATCH 415/436] add id5id to prebid server bid adapter (#4468) --- modules/prebidServerBidAdapter/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 151e880e985..a6061b4bad4 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -698,7 +698,7 @@ const OPEN_RTB_PROTOCOL = { } const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId'); - if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.parrableid || bidUserId.lipb)) { + if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.parrableid || bidUserId.lipb || bidUserId.id5id)) { utils.deepSetValue(request, 'user.ext.eids', []); if (bidUserId.tdid) { @@ -746,6 +746,15 @@ const OPEN_RTB_PROTOCOL = { } request.user.ext.eids.push(liveIntent); } + + if (bidUserId.id5id) { + request.user.ext.eids.push({ + source: 'id5-sync.com', + uids: [{ + id: bidUserId.id5id, + }] + }); + } } if (bidRequests && bidRequests[0].gdprConsent) { From 50bc26cd11860a9e7d9897df2e316ffe00424d5d Mon Sep 17 00:00:00 2001 From: Matt Kendall <1870166+mkendall07@users.noreply.github.com> Date: Wed, 20 Nov 2019 13:44:25 -0500 Subject: [PATCH 416/436] Added _pbjsGlobals for tracking renames. Resolves #4254 (#4419) --- src/prebidGlobal.js | 4 ++++ test/spec/api_spec.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/prebidGlobal.js b/src/prebidGlobal.js index ec685236468..5eed4b3670f 100644 --- a/src/prebidGlobal.js +++ b/src/prebidGlobal.js @@ -4,6 +4,10 @@ window.$$PREBID_GLOBAL$$ = (window.$$PREBID_GLOBAL$$ || {}); window.$$PREBID_GLOBAL$$.cmd = window.$$PREBID_GLOBAL$$.cmd || []; window.$$PREBID_GLOBAL$$.que = window.$$PREBID_GLOBAL$$.que || []; +// create a pbjs global pointer +window._pbjsGlobals = window._pbjsGlobals || []; +window._pbjsGlobals.push('$$PREBID_GLOBAL$$'); + export function getGlobal() { return window.$$PREBID_GLOBAL$$; } diff --git a/test/spec/api_spec.js b/test/spec/api_spec.js index a8987d3ed07..6f21eba7aaf 100755 --- a/test/spec/api_spec.js +++ b/test/spec/api_spec.js @@ -24,6 +24,10 @@ describe('Publisher API', function () { it('should have $$PREBID_GLOBAL$$.que.push function', function () { assert.isFunction($$PREBID_GLOBAL$$.que.push); }); + + it('should have global pointer for PBJS global', function () { + assert.isArray(window._pbjsGlobals); + }); }); describe('has function', function () { From 44fd3c045f6ec7549a7e52d5d33e73f83d96217a Mon Sep 17 00:00:00 2001 From: tadam75 Date: Wed, 20 Nov 2019 21:13:57 +0100 Subject: [PATCH 417/436] Feature/smart video (#4367) * Adding outstream video support. * Fixing unit test. * Adding video instream support. * Handling video startDelay parameter. * Improving unit tests. * Fixing indent. * Handling the request when videoMediaType context is not supported. * Changing maintainer mail address. * Remove video outstream specific code. * Unit test updated. --- modules/smartadserverBidAdapter.js | 52 +++- modules/smartadserverBidAdapter.md | 101 +++++--- .../modules/smartadserverBidAdapter_spec.js | 239 ++++++++++++++---- 3 files changed, 293 insertions(+), 99 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 401c72bffaf..f081c8ac8e1 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -1,4 +1,8 @@ import * as utils from '../src/utils'; +import { + BANNER, + VIDEO +} from '../src/mediaTypes'; import { config } from '../src/config'; @@ -9,6 +13,7 @@ const BIDDER_CODE = 'smartadserver'; export const spec = { code: BIDDER_CODE, aliases: ['smart'], // short code + supportedMediaTypes: [BANNER, VIDEO], /** * Determines whether or not the given bid request is valid. * @@ -33,6 +38,7 @@ export const spec = { // pull requested transaction ID from bidderRequest.bids[].transactionId return validBidRequests.map(bid => { + // Common bid request attributes for banner, outstream and instream. var payload = { siteid: bid.params.siteId, pageid: bid.params.pageId, @@ -44,10 +50,6 @@ export const spec = { 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], - h: size[1] - })), pageDomain: utils.getTopWindowUrl(), transactionId: bid.transactionId, timeout: config.getConfig('bidderTimeout'), @@ -55,6 +57,26 @@ export const spec = { prebidVersion: '$prebid.version$' }; + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + if (!videoMediaType) { + payload.sizes = bid.sizes.map(size => ({ + w: size[0], + h: size[1] + })); + } else if (videoMediaType && videoMediaType.context === 'instream') { + // Specific attributes for instream. + var playerSize = videoMediaType.playerSize[0]; + payload.isVideo = true; + payload.videoData = { + videoProtocol: bid.params.video.protocol, + playerWidth: playerSize[0], + playerHeight: playerSize[1], + adBreak: bid.params.video.startDelay || 0 + }; + } else { + return {}; + } + if (bidderRequest && bidderRequest.gdprConsent) { payload.gdpr_consent = bidderRequest.gdprConsent.consentString; payload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side @@ -74,13 +96,15 @@ export const spec = { * @param {*} serverResponse A successful response from the server. * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: function (serverResponse, bidRequest) { + interpretResponse: function (serverResponse, bidRequestString) { const bidResponses = []; var response = serverResponse.body; try { if (response) { - const bidResponse = { - requestId: JSON.parse(bidRequest.data).bidId, + const bidRequest = JSON.parse(bidRequestString.data); + + var bidResponse = { + requestId: bidRequest.bidId, cpm: response.cpm, width: response.width, height: response.height, @@ -89,10 +113,18 @@ export const spec = { currency: response.currency, netRevenue: response.isNetCpm, ttl: response.ttl, - referrer: utils.getTopWindowUrl(), - adUrl: response.adUrl, - ad: response.ad + referrer: utils.getTopWindowUrl() }; + + if (bidRequest.isVideo) { + bidResponse.mediaType = VIDEO; + bidResponse.vastUrl = response.adUrl; + bidResponse.vastXml = response.ad; + } else { + bidResponse.adUrl = response.adUrl; + bidResponse.ad = response.ad; + } + bidResponses.push(bidResponse); } } catch (error) { diff --git a/modules/smartadserverBidAdapter.md b/modules/smartadserverBidAdapter.md index 1200c0961a0..c1fc0d819c5 100644 --- a/modules/smartadserverBidAdapter.md +++ b/modules/smartadserverBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Smart Ad Server Bidder Adapter Module Type: Bidder Adapter -Maintainer: gcarnec@smartadserver.com +Maintainer: support@smartadserver.com ``` # Description @@ -18,45 +18,72 @@ Please reach out to your Technical account manager for more information. ## Web ``` 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: 62913, - ckId: 1122334455 // optional - } - } - ] - } - ]; + { + code: 'test-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "smart", + params: { + domain: 'http://ww251.smartadserver.com', + siteId: 207435, + pageId: 896536, + formatId: 62913, + 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 - } - } - ] - } - ]; + { + 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 + } + } + ] + } + ]; +``` + +## Instream Video +``` + var videoAdUnit = { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: "smart", + params: { + domain: 'http://ww251.smartadserver.com', + siteId: 326147, + pageId: 1153895, + formatId: 55710 + bidfloor: 5, + video: { + protocol: 6, + startDelay: 0 + } + } + }] + }; ``` \ No newline at end of file diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index c5ae9e59054..30afad308c7 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -100,58 +100,6 @@ describe('Smart bid adapter tests', function () { expect(requestContent).to.have.property('ckid').and.to.equal(42); }); - describe('gdpr tests', function () { - afterEach(function () { - config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeAll(); - }); - - it('Verify build request with GDPR', function () { - 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', function () { - 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', function () { const request = spec.buildRequests(DEFAULT_PARAMS); const bids = spec.interpretResponse(BID_RESPONSE, request[0]); @@ -261,4 +209,191 @@ describe('Smart bid adapter tests', function () { }, []); expect(syncs).to.have.lengthOf(0); }); + + describe('gdpr tests', function () { + afterEach(function () { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeAll(); + }); + + it('Verify build request with GDPR', function () { + 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', function () { + 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=='); + }); + }); + + describe('Instream video tests', function () { + afterEach(function () { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeAll(); + }); + + const INSTREAM_DEFAULT_PARAMS = [{ + adUnitCode: 'sas_42', + bidId: 'abcd1234', + bidder: 'smartadserver', + mediaTypes: { + video: { + context: 'instream', + playerSize: [[640, 480]] // It seems prebid.js transforms the player size array into an array of array... + } + }, + params: { + siteId: '1234', + pageId: '5678', + formatId: '90', + target: 'test=prebid', + bidfloor: 0.420, + buId: '7569', + appName: 'Mozilla', + ckId: 42, + video: { + protocol: 6 + } + }, + requestId: 'efgh5678', + transactionId: 'zsfgzzg' + }]; + + var INSTREAM_BID_RESPONSE = { + body: { + cpm: 12, + width: 640, + height: 480, + creativeId: 'zioeufg', + currency: 'GBP', + isNetCpm: true, + ttl: 300, + adUrl: 'http://awesome.fake-vast.url', + ad: '', + cSyncUrl: 'http://awesome.fake.csync.url' + } + }; + + it('Verify instream video build request', function () { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + } + }); + const request = spec.buildRequests(INSTREAM_DEFAULT_PARAMS); + expect(request[0]).to.have.property('url').and.to.equal('https://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'); + 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('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); + expect(requestContent).to.have.property('isVideo').and.to.equal(true); + expect(requestContent).to.have.property('videoData'); + expect(requestContent.videoData).to.have.property('videoProtocol').and.to.equal(6); + expect(requestContent.videoData).to.have.property('playerWidth').and.to.equal(640); + expect(requestContent.videoData).to.have.property('playerHeight').and.to.equal(480); + }); + + it('Verify instream parse response', function () { + const request = spec.buildRequests(INSTREAM_DEFAULT_PARAMS); + const bids = spec.interpretResponse(INSTREAM_BID_RESPONSE, request[0]); + expect(bids).to.have.lengthOf(1); + const bid = bids[0]; + expect(bid.cpm).to.equal(12); + expect(bid.mediaType).to.equal('video'); + expect(bid.vastUrl).to.equal('http://awesome.fake-vast.url'); + expect(bid.vastXml).to.equal(''); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + 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(INSTREAM_DEFAULT_PARAMS[0].bidId); + expect(bid.referrer).to.equal(utils.getTopWindowUrl()); + + expect(function () { + spec.interpretResponse(INSTREAM_BID_RESPONSE, { + data: 'invalid Json' + }) + }).to.not.throw(); + }); + + it('Verify not handled media type return empty request', function () { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + } + }); + const request = spec.buildRequests([{ + adUnitCode: 'sas_42', + bidder: 'smartadserver', + mediaTypes: { + video: { + context: 'badcontext' + } + }, + params: { + domain: 'http://prg.smartadserver.com', + siteId: '1234', + pageId: '5678', + formatId: '90', + target: 'test=prebid', + bidfloor: 0.420, + buId: '7569', + appName: 'Mozilla', + ckId: 42 + }, + requestId: 'efgh5678', + transactionId: 'zsfgzzg' + }, INSTREAM_DEFAULT_PARAMS[0]]); + expect(request[0]).to.be.empty; + expect(request[1]).to.not.be.empty; + }); + }); }); From 7f7a84d976437606a760caf6ca93919570ec3825 Mon Sep 17 00:00:00 2001 From: Veronica Kim <43146383+vkimcm@users.noreply.github.com> Date: Wed, 20 Nov 2019 15:24:05 -0500 Subject: [PATCH 418/436] do not select element that gets removed after dfp render (#4423) --- src/secureCreatives.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index df7abe4ebee..7584c5d2bf7 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -81,8 +81,9 @@ export function _sendAdToCreative(adObject, remoteDomain, source) { function resizeRemoteCreative({ adUnitCode, width, height }) { // resize both container div + iframe - ['div:last-child', 'div:last-child iframe'].forEach(elmType => { - let element = getElementByAdUnit(elmType); + ['div', 'iframe'].forEach(elmType => { + // not select element that gets removed after dfp render + let element = getElementByAdUnit(elmType + ':not([style*="display: none"])'); if (element) { let elementStyle = element.style; elementStyle.width = width + 'px'; From 6fd6af6e73d83ef7a1732420ee2ebf501e9b73f4 Mon Sep 17 00:00:00 2001 From: songtungmtp <57524426+songtungmtp@users.noreply.github.com> Date: Thu, 21 Nov 2019 05:25:37 +0900 Subject: [PATCH 419/436] add smms adapter (#4439) * add smms adapter * re-run ci, why adigo adapter failed?? * review comments fix, remove deprecated functions, fix unit test --- modules/smmsBidAdapter.js | 155 ++++++++++++++++++++++ modules/smmsBidAdapter.md | 60 +++++++++ test/spec/modules/smmsBidAdapter_spec.js | 161 +++++++++++++++++++++++ 3 files changed, 376 insertions(+) create mode 100644 modules/smmsBidAdapter.js create mode 100644 modules/smmsBidAdapter.md create mode 100644 test/spec/modules/smmsBidAdapter_spec.js diff --git a/modules/smmsBidAdapter.js b/modules/smmsBidAdapter.js new file mode 100644 index 00000000000..dafd4aba734 --- /dev/null +++ b/modules/smmsBidAdapter.js @@ -0,0 +1,155 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; + +const BIDDER_CODE = 'smms'; +const ENDPOINT_BANNER = 'https://bidder.mediams.mb.softbank.jp/api/v1/prebid/banner'; +const ENDPOINT_NATIVE = 'https://bidder.mediams.mb.softbank.jp/api/v1/prebid/native'; +const COOKIE_SYNC_URL = 'https://bidder.mediams.mb.softbank.jp/api/v1/cookie/gen'; +const SUPPORTED_MEDIA_TYPES = ['banner', 'native']; +const SUPPORTED_CURRENCIES = ['USD', 'JPY']; +const DEFAULT_CURRENCY = 'JPY'; +const NET_REVENUE = true; + +function _encodeURIComponent(a) { + let b = window.encodeURIComponent(a); + b = b.replace(/'/g, '%27'); + return b; +} + +export function _getUrlVars(url) { + let hash; + const myJson = {}; + const hashes = url.slice(url.indexOf('?') + 1).split('&'); + for (let i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + myJson[hash[0]] = hash[1]; + } + return myJson; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: SUPPORTED_MEDIA_TYPES, + isBidRequestValid: function(bid) { + let valid = !!(bid.params.placementId); + if (valid && bid.params.hasOwnProperty('currency')) { + if (SUPPORTED_CURRENCIES.indexOf(bid.params.currency) === -1) { + utils.logError('Invalid currency type, we support only JPY and USD!'); + valid = false; + } + } + + return valid; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const serverRequests = []; + let refererInfo; + if (bidderRequest && bidderRequest.refererInfo) { + refererInfo = bidderRequest.refererInfo; + } + + const g = (typeof (geparams) !== 'undefined' && typeof (geparams) == 'object' && geparams) ? geparams : {}; + validBidRequests.forEach((bid, i) => { + let endpoint = ENDPOINT_BANNER; + let data = { + 'placementid': bid.params.placementId, + 'cur': bid.params.hasOwnProperty('currency') ? bid.params.currency : DEFAULT_CURRENCY, + 'ua': navigator.userAgent, + 'adtk': _encodeURIComponent(g.lat ? '0' : '1'), + 'loc': (refererInfo && refererInfo.referer) ? refererInfo.referer : '', + 'topframe': (window.parent == window.self) ? 1 : 0, + 'sw': screen && screen.width, + 'sh': screen && screen.height, + 'cb': Math.floor(Math.random() * 99999999999), + 'tpaf': 1, + 'cks': 1, + 'requestid': bid.bidId, + 'referer': (refererInfo && refererInfo.referer) ? refererInfo.referer : '' + }; + + if (bid.hasOwnProperty('nativeParams')) { + endpoint = ENDPOINT_NATIVE; + data.tkf = 1; // return url tracker + data.ad_track = '1'; + data.apiv = '1.1.0'; + } + + serverRequests.push({ + method: 'GET', + url: endpoint, + data: utils.parseQueryStringParameters(data) + }); + }); + + return serverRequests; + }, + interpretResponse: function(serverResponse, request) { + const data = _getUrlVars(request.data) + const successBid = serverResponse.body || {}; + let bidResponses = []; + if (successBid.hasOwnProperty(data.placementid)) { + let bid = successBid[data.placementid] + let bidResponse = { + requestId: bid.requestid, + cpm: bid.price, + creativeId: bid.creativeId, + currency: bid.cur, + netRevenue: NET_REVENUE, + ttl: 700 + }; + + if (bid.hasOwnProperty('title')) { // it is native ad response + bidResponse.mediaType = 'native' + bidResponse.native = { + title: bid.title, + body: bid.description, + cta: bid.cta, + sponsoredBy: bid.advertiser, + clickUrl: _encodeURIComponent(bid.landingURL), + impressionTrackers: bid.trackings, + } + if (bid.screenshots) { + bidResponse.native.image = { + url: bid.screenshots.url, + height: bid.screenshots.height, + width: bid.screenshots.width, + } + } + if (bid.icon) { + bidResponse.native.icon = { + url: bid.icon.url, + height: bid.icon.height, + width: bid.icon.width, + } + } + } else { + bidResponse.ad = bid.adm + bidResponse.width = bid.width + bidResponse.height = bid.height + } + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses) { + let syncs = [] + syncs.push({ + type: 'image', + url: COOKIE_SYNC_URL + }) + + return syncs; + }, + onTimeout: function(timeoutData) {}, + onBidWon: function(bid) {}, + onSetTargeting: function(bid) {} +} +registerBidder(spec); diff --git a/modules/smmsBidAdapter.md b/modules/smmsBidAdapter.md new file mode 100644 index 00000000000..f1d6e233f96 --- /dev/null +++ b/modules/smmsBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +Module Name: SMMS Bid Adapter + +Maintainer: SBBGRP-SSP-PMP@g.softbank.co.jp + +# Description + +Module that connects to softbank's demand sources + +# Test Parameters + +```javascript + var adUnits = [ + { + code: 'test', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [ + { + bidder: 'smms', + params: { + placementId: 1440837, + currency: 'USD' + } + } + ] + }, + { + code: 'test', + mediaTypes: { + native: { + title: { + required: true, + len: 80 + }, + image: { + required: true, + sizes: [150, 50] + }, + sponsoredBy: { + required: true + } + } + }, + bids: [ + { + bidder: 'smms', + params: { + placementId: 1440838, + currency: 'USD' + } + }, + ], + } + ]; +``` diff --git a/test/spec/modules/smmsBidAdapter_spec.js b/test/spec/modules/smmsBidAdapter_spec.js new file mode 100644 index 00000000000..3ed952811ea --- /dev/null +++ b/test/spec/modules/smmsBidAdapter_spec.js @@ -0,0 +1,161 @@ +import {expect} from 'chai'; +import {spec, _getUrlVars} from 'modules/smmsBidAdapter'; +import * as utils from 'src/utils'; + +const BASE_URI = 'https://bidder.mediams.mb.softbank.jp/api/v1/prebid/banner' +const NATIVE_BASE_URI = 'https://bidder.mediams.mb.softbank.jp/api/v1/prebid/native' + +describe('smms adapter', function() { + let bidRequests; + let nativeBidRequests; + + beforeEach(function() { + bidRequests = [ + { + bidder: 'smms', + params: { + placementId: 1440837, + currency: 'USD' + } + } + ] + + nativeBidRequests = [ + { + bidder: 'smms', + params: { + placementId: 1440838, + currency: 'USD' + }, + nativeParams: { + title: { + required: true, + len: 80 + }, + image: { + required: true, + sizes: [150, 50] + }, + sponsoredBy: { + required: true + } + } + } + ] + }) + + describe('isBidRequestValid', function () { + it('valid bid case: required params found', function () { + let validBid = { + bidder: 'smms', + params: { + placementId: 1440837, + currency: 'USD' + } + } + let isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('invalid bid case: placementId is not passed', function() { + let validBid = { + bidder: 'smms', + params: { + } + } + let isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }) + + it('invalid bid case: currency is not support', function() { + let validBid = { + bidder: 'smms', + params: { + placementId: 1440837, + currency: 'AUD' + } + } + let isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }) + }) + + describe('buildRequests', function () { + it('sends bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(BASE_URI); + expect(request.method).to.equal('GET'); + }); + + it('sends native bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(nativeBidRequests)[0]; + expect(request.url).to.equal(NATIVE_BASE_URI); + expect(request.method).to.equal('GET'); + }); + + it('buildRequests function should not modify original bidRequests object', function () { + let originalBidRequests = utils.deepClone(bidRequests); + spec.buildRequests(bidRequests); + expect(bidRequests).to.deep.equal(originalBidRequests); + }); + + it('buildRequests function should not modify original nativeBidRequests object', function () { + let originalBidRequests = utils.deepClone(nativeBidRequests); + spec.buildRequests(nativeBidRequests); + expect(nativeBidRequests).to.deep.equal(originalBidRequests); + }); + + it('Request params check', function() { + let request = spec.buildRequests(bidRequests)[0]; + const data = _getUrlVars(request.data) + expect(parseInt(data.placementid)).to.exist.and.to.equal(bidRequests[0].params.placementId); + expect(data.cur).to.exist.and.to.equal(bidRequests[0].params.currency); + }) + + it('Native request params check', function() { + let request = spec.buildRequests(nativeBidRequests)[0]; + const data = _getUrlVars(request.data) + expect(parseInt(data.placementid)).to.exist.and.to.equal(nativeBidRequests[0].params.placementId); + expect(data.cur).to.exist.and.to.equal(nativeBidRequests[0].params.currency); + }) + }) + + describe('interpretResponse', function () { + let response = { + 1440837: + { + 'creativeId': '', + 'cur': 'USD', + 'price': 0.0920, + 'width': 300, + 'height': 250, + 'requestid': '2e42361a6172bf', + 'adm': '' + } + } + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '2e42361a6172bf', + 'cpm': 0.0920, + 'width': 300, + 'height': 250, + 'netRevenue': true, + 'currency': 'USD', + 'creativeId': '', + 'ttl': 700, + 'ad': '' + } + ]; + let request = spec.buildRequests(bidRequests)[0]; + let result = spec.interpretResponse({body: response}, request); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + expect(result[0].cpm).to.not.equal(null); + expect(result[0].creativeId).to.not.equal(null); + expect(result[0].ad).to.not.equal(null); + expect(result[0].currency).to.equal('USD'); + expect(result[0].netRevenue).to.equal(true); + }); + }) +}) From 0cf481d9eda87672f1271f62cc0029021a0e6df8 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Nov 2019 15:28:37 -0500 Subject: [PATCH 420/436] Prebid 2.41.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9db7109a48e..6c25fe0b812 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.41.0i-pre", + "version": "2.41.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 9b8dee61337e6e44669414c6d0b43fb4a7fceaa7 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Wed, 20 Nov 2019 15:37:45 -0500 Subject: [PATCH 421/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c25fe0b812..a4656275405 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.41.0", + "version": "2.42.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 8ebf2f02bbb889471c5e1407bb1716e9a7ba9c2f Mon Sep 17 00:00:00 2001 From: susyt Date: Thu, 21 Nov 2019 06:27:46 -0800 Subject: [PATCH 422/436] adds schain param (#4442) --- modules/gumgumBidAdapter.js | 26 +++++++++++++++++++ test/spec/modules/gumgumBidAdapter_spec.js | 30 +++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 585d3279a07..df6ca1971ee 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -98,6 +98,28 @@ function _getDigiTrustQueryParams(userId) { }; } +/** + * Serializes the supply chain object according to IAB standards + * @see https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + * @param {Object} schainObj supply chain object + * @returns {string} + */ +function _serializeSupplyChainObj(schainObj) { + let serializedSchain = `${schainObj.ver},${schainObj.complete}`; + + // order of properties: asi,sid,hp,rid,name,domain + schainObj.nodes.map(node => { + serializedSchain += `!${encodeURIComponent(node['asi'] || '')},`; + serializedSchain += `${encodeURIComponent(node['sid'] || '')},`; + serializedSchain += `${encodeURIComponent(node['hp'] || '')},`; + serializedSchain += `${encodeURIComponent(node['rid'] || '')},`; + serializedSchain += `${encodeURIComponent(node['name'] || '')},`; + serializedSchain += `${encodeURIComponent(node['domain'] || '')}`; + }) + + return serializedSchain; +} + /** * Determines whether or not the given bid request is valid. * @@ -141,6 +163,7 @@ function buildRequests (validBidRequests, bidderRequest) { const { bidId, params = {}, + schain, transactionId, userId = {} } = bidRequest; @@ -171,6 +194,9 @@ function buildRequests (validBidRequests, bidderRequest) { if (data.gdprApplies) { data.gdprConsent = gdprConsent.consentString; } + if (schain && schain.nodes) { + data.schain = _serializeSupplyChainObj(schain); + } bids.push({ id: bidId, diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 0d00eb2b93c..97897a11ed3 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -74,7 +74,29 @@ describe('gumgumAdapter', function () { }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e' + 'bidId': '30b31c1838de1e', + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1, + 'rid': 'bid-request-2', + 'name': 'intermediary', + 'domain': 'intermediary.com' + } + ] + } } ]; @@ -140,6 +162,12 @@ describe('gumgumAdapter', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.data).to.not.include.any.keys('tdid'); }); + it('should send schain parameter in serialized form', function () { + const serializedForm = '1.0,1!exchange1.com,1234,1,bid-request-1,publisher,publisher.com!exchange2.com,abcd,1,bid-request-2,intermediary,intermediary.com' + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data).to.include.any.keys('schain'); + expect(request.data.schain).to.eq(serializedForm); + }); it('should send ns parameter if browser contains navigator.connection property', function () { const bidRequest = spec.buildRequests(bidRequests)[0]; const connection = window.navigator && window.navigator.connection; From e2615de673a2ae36a8f2c87ec8d90ce9fb87aec2 Mon Sep 17 00:00:00 2001 From: z-sunshine <33084773+z-sunshine@users.noreply.github.com> Date: Fri, 22 Nov 2019 20:19:57 +0800 Subject: [PATCH 423/436] Create newborntownWeb adapter (#4455) * Create newborntownWeb adapter * only https protocol --- modules/newborntownWebBidAdapter.js | 156 ++++++++++++++++++ modules/newborntownWebBidAdapter.md | 35 ++++ .../modules/newborntownWebBidAdapter_spec.js | 152 +++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 modules/newborntownWebBidAdapter.js create mode 100644 modules/newborntownWebBidAdapter.md create mode 100644 test/spec/modules/newborntownWebBidAdapter_spec.js diff --git a/modules/newborntownWebBidAdapter.js b/modules/newborntownWebBidAdapter.js new file mode 100644 index 00000000000..103fac7ba6a --- /dev/null +++ b/modules/newborntownWebBidAdapter.js @@ -0,0 +1,156 @@ +import * as utils from '../src/utils'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {BANNER, NATIVE} from '../src/mediaTypes'; +const BIDDER_CODE = 'newborntownWeb'; + +const REQUEST_URL = 'https://us-west.solortb.com/adx/api/rtb?from=4' + +function randomn(n) { + return parseInt((Math.random() + 1) * Math.pow(10, n - 1)) + ''; +} +function generateGUID() { + var d = new Date().getTime(); + var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); + }) + return guid; +} +function _isMobile() { + return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); +} +function _isConnectedTV() { + return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); +} +function _getDeviceType() { + return _isMobile() ? 1 : _isConnectedTV() ? 3 : 2; +} +var platform = (function getPlatform() { + var ua = navigator.userAgent; + if (ua.indexOf('Android') > -1 || ua.indexOf('Adr') > -1) { + return 'Android' + } + if (ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) { + return 'iOS' + } + return 'windows' +})(); +function getLanguage() { + const language = navigator.language ? 'language' : 'userLanguage'; + return navigator[language].split('-')[0]; +} +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, NATIVE], + isBidRequestValid: function(bid) { + return !!(bid.params.publisher_id && bid.params.slot_id && bid.params.bidfloor); + }, + + buildRequests: function(validBidRequests, bidderRequest) { + let requestArr = [] + if (validBidRequests.length === 0) { + return null; + } + var guid; + if (localStorage.getItem('sax_user_id') == null) { + localStorage.setItem('sax_user_id', generateGUID()) + } + guid = localStorage.getItem('sax_user_id') + utils._each(validBidRequests, function(bidRequest) { + const bidRequestObj = bidRequest.params + var req = { + id: randomn(12) + randomn(12), + tmax: bidderRequest.timeout, + bidId: bidRequest.bidId, + user: { + id: guid + }, + imp: [ + { + id: '1', + bidfloor: bidRequestObj.bidfloor, + bidfloorcur: 'USD', + banner: { + w: 0, + h: 0 + } + } + ], + site: { + domain: window.location.host, + id: bidRequestObj.slot_id, + page: window.location.href, + publisher: { + id: bidRequestObj.publisher_id + }, + }, + device: { + ip: '', + ua: navigator.userAgent, + os: platform, + geo: { + country: '', + type: 0, + ipservice: 1, + region: '', + city: '', + }, + language: getLanguage(), + devicetype: _getDeviceType() + }, + ext: { + solomath: { + slotid: bidRequestObj.slot_id + } + } + }; + var sizes = bidRequest.sizes; + if (sizes) { + if (sizes && utils.isArray(sizes[0])) { + req.imp[0].banner.w = sizes[0][0]; + req.imp[0].banner.h = sizes[0][1]; + } else if (sizes && utils.isNumber(sizes[0])) { + req.imp[0].banner.w = sizes[0]; + req.imp[0].banner.h = sizes[1]; + } + } else { + return false; + } + const options = { + withCredentials: false + } + requestArr.push({ + method: 'POST', + url: REQUEST_URL, + data: req, + bidderRequest, + options: options + }) + }) + return requestArr; + }, + interpretResponse: function(serverResponse, request) { + var bidResponses = []; + if (serverResponse.body.seatbid && serverResponse.body.seatbid.length > 0 && serverResponse.body.seatbid[0].bid && serverResponse.body.seatbid[0].bid.length > 0 && serverResponse.body.seatbid[0].bid[0].adm) { + utils._each(serverResponse.body.seatbid[0].bid, function(bodyAds) { + var adstr = ''; + adstr = bodyAds.adm; + var bidResponse = { + requestId: request.data.bidId || 0, + cpm: bodyAds.price || 0, + width: bodyAds.w ? bodyAds.w : 0, + height: bodyAds.h ? bodyAds.h : 0, + ad: adstr, + netRevenue: true, + currency: serverResponse.body.cur || 'USD', + ttl: 600, + creativeId: bodyAds.cid + }; + bidResponses.push(bidResponse); + }); + } + return bidResponses; + } +} +registerBidder(spec); diff --git a/modules/newborntownWebBidAdapter.md b/modules/newborntownWebBidAdapter.md new file mode 100644 index 00000000000..f607369ffb6 --- /dev/null +++ b/modules/newborntownWebBidAdapter.md @@ -0,0 +1,35 @@ +# Overview + +``` +Module Name: NewborntownWeb Bidder Adapter +Module Type: Bidder Adapter +Maintainer: zhuyushuang@newborntown.com +``` + +# Description + +Integration for website + +# Test Parameters +``` + var adUnits = [ + { + code: '/19968336/header-bid-tag-1', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: "newborntownWeb", + params: { + 'publisher_id': '1238122', + 'slot_id': '123123', + 'bidfloor': 0.2 + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/newborntownWebBidAdapter_spec.js b/test/spec/modules/newborntownWebBidAdapter_spec.js new file mode 100644 index 00000000000..d7cf4a7dd95 --- /dev/null +++ b/test/spec/modules/newborntownWebBidAdapter_spec.js @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import {spec} from 'modules/newborntownWebBidAdapter'; +describe('NewborntownWebAdapter', function() { + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'newborntownWeb', + 'params': { + 'publisher_id': '1238122', + 'slot_id': '123123', + 'bidfloor': 0.3 + }, + 'adUnitCode': '/19968336/header-bid-tag-1', + 'sizes': [[300, 250]], + 'bidId': '2e9cf65f23dbd9', + 'bidderRequestId': '1f01d9d22ee657', + 'auctionId': '2bf455a4-a889-41d5-b48f-9b56b89fbec7', + } + it('should return true where required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }) + describe('buildRequests', function () { + let bidderRequest = { + 'bidderCode': 'newborntownWeb', + 'bidderRequestId': '1f5c279a4c5de3', + 'bids': [ + { + 'bidder': 'newborntownWeb', + 'params': { + 'publisher_id': '1238122', + 'slot_id': '123123', + 'bidfloor': 0.3 + }, + 'mediaTypes': { + 'banner': {'sizes': [[300, 250]]} + }, + 'adUnitCode': '/19968336/header-bid-tag-1', + 'transactionId': '9b954797-d6f4-4730-9cbe-5a1bc8480f52', + 'sizes': [[300, 250]], + 'bidId': '215f48d07eb8b8', + 'bidderRequestId': '1f5c279a4c5de3', + 'auctionId': '5ed4f607-e11c-45b0-aba9-f67768e1f9f4', + 'src': 'client', + 'bidRequestsCount': 1 + } + ], + 'auctionStart': 1573123289380, + 'timeout': 9000, + 'start': 1573123289383 + } + const request = spec.buildRequests(bidderRequest['bids'], bidderRequest); + it('Returns POST method', function () { + expect(request[0].method).to.equal('POST'); + expect(request[0].url.indexOf('//us-west.solortb.com/adx/api/rtb?from=4') !== -1).to.equal(true); + expect(request[0].data).to.exist; + }); + it('request params multi size format object check', function () { + let bidderRequest = { + 'bidderCode': 'newborntownWeb', + 'bidderRequestId': '1f5c279a4c5de3', + 'bids': [ + { + 'bidder': 'newborntownWeb', + 'params': { + 'publisher_id': '1238122', + 'slot_id': '123123', + 'bidfloor': 0.3 + }, + 'mediaTypes': { + 'native': {'sizes': [[300, 250]]} + }, + 'adUnitCode': '/19968336/header-bid-tag-1', + 'transactionId': '9b954797-d6f4-4730-9cbe-5a1bc8480f52', + 'sizes': [300, 250], + 'bidId': '215f48d07eb8b8', + 'bidderRequestId': '1f5c279a4c5de3', + 'auctionId': '5ed4f607-e11c-45b0-aba9-f67768e1f9f4', + 'src': 'client', + 'bidRequestsCount': 1 + } + ], + 'auctionStart': 1573123289380, + 'timeout': 9000, + 'start': 1573123289383 + } + let requstTest = spec.buildRequests(bidderRequest['bids'], bidderRequest) + expect(requstTest[0].data.imp[0].banner.w).to.equal(300); + expect(requstTest[0].data.imp[0].banner.h).to.equal(250); + }); + }) + describe('interpretResponse', function () { + let serverResponse; + let bidRequest = { + data: { + bidId: '2d359291dcf53b' + } + }; + beforeEach(function () { + serverResponse = { + 'body': { + 'id': '174548259807190369860081', + 'seatbid': [ + { + 'bid': [ + { + 'id': '1573540665390298996', + 'impid': '1', + 'price': 0.3001, + 'adid': '1573540665390299172', + 'nurl': 'https://us-west.solortb.com/winnotice?price=${AUCTION_PRICE}&ssp=4&req_unique_id=740016d1-175b-4c19-9744-58a59632dabe&unique_id=06b08e40-2489-439a-8f9e-6413f3dd0bc8&isbidder=1&up=bQyvVo7tgbBVW2dDXzTdBP95Mv35YqqEika0T_btI1h6xjqA8GSXQe51_2CCHQcfuwAEOgdwN8u3VgUHmCuqNPKiBmIPaYUOQBBKjJr05zeKtabKnGT7_JJKcurrXqQ5Sl804xJear_qf2-jOaKB4w', + 'adm': "
", + 'adomain': [ + 'newborntown.com' + ], + 'iurl': 'https://sdkvideo.s3.amazonaws.com/4aa1d9533c4ce71bb1cf750ed38e3a58.png', + 'cid': '345', + 'crid': '41_11113', + 'cat': [ + '' + ], + 'h': 250, + 'w': 300 + } + ], + 'seat': '1' + } + ], + 'bidid': 'bid1573540665390298585' + }, + 'headers': { + + } + } + }); + it('result is correct', function () { + const result = spec.interpretResponse(serverResponse, bidRequest); + if (result && result[0]) { + expect(result[0].requestId).to.equal('2d359291dcf53b'); + expect(result[0].cpm).to.equal(0.3001); + expect(result[0].width).to.equal(300); + expect(result[0].height).to.equal(250); + expect(result[0].creativeId).to.equal('345'); + } + }); + }) +}) From e3011f5e82470eda8404b2fe7859f3bacba622db Mon Sep 17 00:00:00 2001 From: oasis <2394426+bmwcmw@users.noreply.github.com> Date: Mon, 25 Nov 2019 01:50:26 +0100 Subject: [PATCH 424/436] Provide criteoId to server by user.ext.eids (#4478) --- modules/prebidServerBidAdapter/index.js | 11 ++++++++++- test/spec/modules/prebidServerBidAdapter_spec.js | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index a6061b4bad4..9371083c8d2 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -698,7 +698,7 @@ const OPEN_RTB_PROTOCOL = { } const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId'); - if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.parrableid || bidUserId.lipb || bidUserId.id5id)) { + if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid || bidUserId.parrableid || bidUserId.lipb || bidUserId.id5id || bidUserId.criteoId)) { utils.deepSetValue(request, 'user.ext.eids', []); if (bidUserId.tdid) { @@ -755,6 +755,15 @@ const OPEN_RTB_PROTOCOL = { }] }); } + + if (bidUserId.criteoId) { + request.user.ext.eids.push({ + source: 'criteo.com', + uids: [{ + id: bidUserId.criteoId + }] + }); + } } if (bidRequests && bidRequests[0].gdprConsent) { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 76860a09ee2..5ee05ad401e 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1079,6 +1079,7 @@ describe('S2S Adapter', function () { let userIdBidRequest = utils.deepClone(BID_REQUESTS); userIdBidRequest[0].bids[0].userId = { + criteoId: '44VmRDeUE3ZGJ5MzRkRVJHU3BIUlJ6TlFPQUFU', tdid: 'abc123', pubcid: '1234', parrableid: '01.1563917337.test-eid', @@ -1094,6 +1095,8 @@ describe('S2S Adapter', function () { expect(Array.isArray(requestBid.user.ext.eids)).to.be.true; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'criteo.com')).is.not.empty; + expect(requestBid.user.ext.eids.filter(eid => eid.source === 'criteo.com')[0].uids[0].id).is.equal('44VmRDeUE3ZGJ5MzRkRVJHU3BIUlJ6TlFPQUFU'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')).is.not.empty; expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234'); expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')).is.not.empty; From 95bc50003a4312469027439bbf2036c7245d0512 Mon Sep 17 00:00:00 2001 From: ucfunnel <39581136+ucfunnel@users.noreply.github.com> Date: Mon, 25 Nov 2019 08:54:41 +0800 Subject: [PATCH 425/436] ucfunnel adapter fix error message in debug mode (#4338) * Add a new ucfunnel Adapter and test page * Add a new ucfunnel Adapter and test page * 1. Use prebid lib in the repo to keep updated 2. Replace var with let 3. Put JSON.parse(JSON.stringify()) into try catch block * utils.getTopWindowLocation is a function * Change to modules from adapters * Migrate to module design * [Dev Fix] Remove width and height which can be got from ad unit id * Update ucfunnelBidAdapter to fit into new spec * Correct the endpoint. Fix the error of query string * Add test case for ucfunnelBidAdapter * Fix lint error * Update version number * Combine all checks on bid request * Add GDPR support for ucfunnel adapter * Add in-stream video and native support for ucfunnel adapter * Remove demo page. Add more test cases. * Change request method from POST to GET * Remove unnecessary comment * Support vastXml and vastUrl for video request * update TTL to 30 mins * Avoid using arrow function which is not discuraged in mocha * ucfunnel tdid support * ucfunnel fix error message in debug mode --- modules/ucfunnelBidAdapter.js | 9 +++++---- test/spec/modules/ucfunnelBidAdapter_spec.js | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index 3a7441e7374..43c125c2a96 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -64,7 +64,7 @@ export const spec = { let bid = { requestId: bidRequest.bidId, cpm: ad.cpm || 0, - creativeId: ad.ad_id, + creativeId: ad.ad_id || bidRequest.params.adid, dealId: ad.deal || null, currency: 'USD', netRevenue: true, @@ -108,10 +108,11 @@ export const spec = { break; case BANNER: default: + var size = parseSizes(bidRequest); Object.assign(bid, { - width: ad.width, - height: ad.height, - ad: ad.adm + width: ad.width || size[0], + height: ad.height || size[1], + ad: ad.adm || '' }); } diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js index 9618aa8df69..617f4bb69e8 100644 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -47,6 +47,8 @@ const validBannerBidRes = { width: 300 }; +const invalidBannerBidRes = ''; + const validVideoBidReq = { bidder: BIDDER_CODE, params: { @@ -162,6 +164,24 @@ describe('ucfunnel Adapter', function () { }); }); + describe('handle banner no ad', function () { + const request = spec.buildRequests([ validBannerBidReq ]); + const result = spec.interpretResponse({body: invalidBannerBidRes}, request[0]); + it('should build bid array for banner', function () { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', function () { + const bid = result[0]; + + expect(bid.ad).to.exist; + expect(bid.requestId).to.equal('263be71e91dd9d'); + expect(bid.cpm).to.equal(0); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + }); + }); + describe('should support video', function () { const request = spec.buildRequests([ validVideoBidReq ]); const result = spec.interpretResponse({body: validVideoBidRes}, request[0]); From 0c0fb18cb53b87eece114c03bbcc257473e220ee Mon Sep 17 00:00:00 2001 From: Rich Snapp Date: Mon, 25 Nov 2019 08:24:18 -0700 Subject: [PATCH 426/436] explicitly check undefined to allow falsey values in getConfig (#4486) --- src/config.js | 4 ++-- test/spec/unit/core/adapterManager_spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config.js b/src/config.js index b5b1e92dd41..38697c363b3 100644 --- a/src/config.js +++ b/src/config.js @@ -221,9 +221,9 @@ export function newConfig() { const configTopicSet = new Set(Object.keys(config).concat(Object.keys(currBidderConfig))); return from(configTopicSet).reduce((memo, topic) => { - if (!currBidderConfig[topic]) { + if (typeof currBidderConfig[topic] === 'undefined') { memo[topic] = config[topic]; - } else if (!config[topic]) { + } else if (typeof config[topic] === 'undefined') { memo[topic] = currBidderConfig[topic]; } else { if (utils.isPlainObject(currBidderConfig[topic])) { diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 504e4d326ec..bd8f880378b 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -193,7 +193,7 @@ describe('adapterManager tests', function () { bidders: [ 'rubicon' ], config: { buildRequests: 'rubiconBuild', - interpretResponse: 'rubiconInterpret' + interpretResponse: null } }); config.setBidderConfig({ @@ -230,7 +230,7 @@ describe('adapterManager tests', function () { 'rubiconBuild', { speedy: true }, { amazing: true }, - 'rubiconInterpret', + null, 'anotherBaseInterpret' ] }); From 201340ef472e65d52cebba3b3b782ad6510ad83e Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Mon, 25 Nov 2019 07:47:53 -0800 Subject: [PATCH 427/436] Conversant Bid Adapter handles vast xml (#4492) --- modules/conversantBidAdapter.js | 7 ++++++- test/spec/modules/conversantBidAdapter_spec.js | 13 ++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index 9ad1357fa2a..3ffc54bbe80 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -196,7 +196,12 @@ export const spec = { }; if (request.video) { - bid.vastUrl = responseAd; + if (responseAd.charAt(0) === '<') { + bid.vastXml = responseAd; + } else { + bid.vastUrl = responseAd; + } + bid.mediaType = 'video'; bid.width = request.video.w; bid.height = request.video.h; diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 37a13312619..ca6890ceedb 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -156,6 +156,14 @@ describe('Conversant adapter tests', function() { price: 3.99, adomain: ['https://example.com'], id: 'bid003' + }, { + nurl: 'notify004', + adm: '', + crid: '1004', + impid: 'bid004', + price: 4.99, + adomain: ['https://example.com'], + id: 'bid004' }] }] }, @@ -315,7 +323,7 @@ describe('Conversant adapter tests', function() { it('Verify interpretResponse', function() { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponses, request); - expect(response).to.be.an('array').with.lengthOf(3); + expect(response).to.be.an('array').with.lengthOf(4); let bid = response[0]; expect(bid).to.have.property('requestId', 'bid000'); @@ -352,6 +360,9 @@ describe('Conversant adapter tests', function() { expect(bid).to.have.property('mediaType', 'video'); expect(bid).to.have.property('ttl', 300); expect(bid).to.have.property('netRevenue', true); + + bid = response[3]; + expect(bid).to.have.property('vastXml', ''); }); it('Verify handling of bad responses', function() { From c180628753a35ffb594c5156618675b6ce00cde0 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Tue, 26 Nov 2019 14:53:57 -0600 Subject: [PATCH 428/436] [feature] Add a config list of submodules that require refreshing the stored ID after each bid request (#4325) * add a feature to always refresh stored id on each bid request for submodules that require that * update test comments --- modules/userId/index.js | 4 ++ src/constants.json | 3 ++ test/spec/modules/userId_spec.js | 70 ++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/modules/userId/index.js b/modules/userId/index.js index ac96fd2cec8..91eaff13d47 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -386,6 +386,10 @@ function initSubmodules(submodules, consentData) { refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > submodule.config.storage.refreshInSeconds * 1000); } + if (CONSTANTS.SUBMODULES_THAT_ALWAYS_REFRESH_ID[submodule.config.name] === true) { + refreshNeeded = true; + } + if (!storedId || refreshNeeded) { // No previously saved id. Request one from submodule. response = submodule.submodule.getId(submodule.config.params, consentData, storedId); diff --git a/src/constants.json b/src/constants.json index 99e2bd792b9..d993a6531ad 100644 --- a/src/constants.json +++ b/src/constants.json @@ -95,5 +95,8 @@ "BID_STATUS" : { "BID_TARGETING_SET": "targetingSet", "RENDERED": "rendered" + }, + "SUBMODULES_THAT_ALWAYS_REFRESH_ID": { + "parrableId": true } } diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index cd72ca9670f..4058f4435ca 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -985,6 +985,7 @@ describe('User ID', function() { sinon.stub(utils, 'triggerPixel'); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); afterEach(function() { @@ -993,6 +994,7 @@ describe('User ID', function() { utils.triggerPixel.restore(); utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + utils.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); it('pubcid callback with url', function () { @@ -1042,5 +1044,73 @@ describe('User ID', function() { events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); expect(requests[0].url).to.equal('//match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); }); + + it('callback for submodules that always need to refresh stored id', function(done) { + let adUnits = [getAdUnitMock()]; + let innerAdUnits; + const parrableStoredId = '01.1111111111.test-eid'; + const parrableRefreshedId = '02.2222222222.test-eid'; + utils.setCookie('_parrable_eid', parrableStoredId, (new Date(Date.now() + 5000).toUTCString())); + + const parrableIdSubmoduleMock = { + name: 'parrableId', + decode: function(value) { + return { 'parrableid': value }; + }, + getId: function() { + return { + callback: function(cb) { + cb(parrableRefreshedId); + } + }; + } + }; + + const parrableConfigMock = { + userSync: { + syncDelay: 0, + userIds: [{ + name: 'parrableId', + storage: { + type: 'cookie', + name: '_parrable_eid' + } + }] + } + }; + + setSubmoduleRegistry([parrableIdSubmoduleMock]); + attachIdSystem(parrableIdSubmoduleMock); + init(config); + config.setConfig(parrableConfigMock); + + // make first bid request, should use stored id value + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + innerAdUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.parrableid'); + expect(bid.userId.parrableid).to.equal(parrableStoredId); + }); + }); + + // attach a handler for auction end event to run the second bid request + events.on(CONSTANTS.EVENTS.AUCTION_END, function handler(submodule) { + if (submodule === 'parrableIdSubmoduleMock') { + // make the second bid request, id should have been refreshed + requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + innerAdUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.parrableid'); + expect(bid.userId.parrableid).to.equal(parrableRefreshedId); + }); + }); + events.off(CONSTANTS.EVENTS.AUCTION_END, handler); + done(); + } + }); + + // emit an auction end event to run the submodule callback + events.emit(CONSTANTS.EVENTS.AUCTION_END, 'parrableIdSubmoduleMock'); + }); }); }); From 25d06b380d7938685b474eac936c0038646bcfe2 Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 26 Nov 2019 16:24:30 -0500 Subject: [PATCH 429/436] Prebid 2.42.0 Release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4656275405..34f6ec3acac 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.42.0-pre", + "version": "2.42.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 22962d12be15c0df1059895bd2001ab2791e269d Mon Sep 17 00:00:00 2001 From: Bret Gorsline Date: Tue, 26 Nov 2019 16:40:43 -0500 Subject: [PATCH 430/436] Increment pre version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 34f6ec3acac..66cf46e6c8d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "2.42.0", + "version": "2.43.0-pre", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { From 9d7fec7f917e0812ccc6afdf0e8f55753257bc50 Mon Sep 17 00:00:00 2001 From: Sander Date: Wed, 27 Nov 2019 14:51:07 +0100 Subject: [PATCH 431/436] Make adhese adapter prebid 3.0 compatible (#4507) * Added 'adhese' attribute to bid that contains meta data - Jira AD-2642 * added DALE to adhese determination * extra config option: no format, but use size array as format string * Read sizes from mediaTypes.banner.sizes + Apply Eslint suggestions * Use map and join, add originData to response * properly use originData obj * Remove duplicated ids * Update tests --- modules/adheseBidAdapter.js | 40 ++++++++++++++++------ test/spec/modules/adheseBidAdapter_spec.js | 33 ++++++++++++++++++ 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/modules/adheseBidAdapter.js b/modules/adheseBidAdapter.js index 6ca8c8a6aa6..445c9956410 100644 --- a/modules/adheseBidAdapter.js +++ b/modules/adheseBidAdapter.js @@ -11,7 +11,7 @@ export const spec = { supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function(bid) { - return !!(bid.params.account && bid.params.location && bid.params.format); + return !!(bid.params.account && bid.params.location && (bid.params.format || bid.mediaTypes.banner.sizes)); }, buildRequests: function(validBidRequests, bidderRequest) { @@ -83,7 +83,10 @@ function adResponse(bid, ad) { width: Number(ad.width), height: Number(ad.height), creativeId: adDetails.creativeId, - dealId: adDetails.dealId + dealId: adDetails.dealId, + adhese: { + originData: adDetails.originData + } }); if (bidResponse.mediaType === VIDEO) { @@ -112,7 +115,19 @@ function mergeTargets(targets, target) { } function bidToSlotName(bid) { - return bid.params.location + '-' + bid.params.format; + if (bid.params.format) { + return bid.params.location + '-' + bid.params.format; + } + + var sizes = bid.mediaTypes.banner.sizes; + sizes.sort(); + var format = sizes.map(size => size[0] + 'x' + size[1]).join('_'); + + if (format.length > 0) { + return bid.params.location + '-' + format; + } else { + return bid.params.location; + } } function getAccount(validBidRequests) { @@ -150,22 +165,27 @@ function getPrice(ad) { function getAdDetails(ad) { let creativeId = ''; let dealId = ''; + let originData = {}; if (isAdheseAd(ad)) { creativeId = ad.id; dealId = ad.orderId; + originData = { priority: ad.priority, orderProperty: ad.orderProperty, adFormat: ad.adFormat, adType: ad.adType, libId: ad.libId, adspaceId: ad.adspaceId, viewableImpressionCounter: ad.viewableImpressionCounter }; } else { creativeId = ad.origin + (ad.originInstance ? '-' + ad.originInstance : ''); - if (ad.originData && ad.originData.seatbid && ad.originData.seatbid.length) { - const seatbid = ad.originData.seatbid[0]; - if (seatbid.bid && seatbid.bid.length) { - const bid = seatbid.bid[0]; - creativeId = String(bid.crid || ''); - dealId = String(bid.dealid || ''); + if (ad.originData) { + originData = ad.originData; + if (ad.originData.seatbid && ad.originData.seatbid.length) { + const seatbid = ad.originData.seatbid[0]; + if (seatbid.bid && seatbid.bid.length) { + const bid = seatbid.bid[0]; + creativeId = String(bid.crid || ''); + dealId = String(bid.dealid || ''); + } } } } - return { creativeId: creativeId, dealId: dealId }; + return { creativeId: creativeId, dealId: dealId, originData: originData }; } function base64urlEncode(s) { diff --git a/test/spec/modules/adheseBidAdapter_spec.js b/test/spec/modules/adheseBidAdapter_spec.js index 348fb772319..32658e2bb27 100644 --- a/test/spec/modules/adheseBidAdapter_spec.js +++ b/test/spec/modules/adheseBidAdapter_spec.js @@ -153,6 +153,16 @@ describe('AdheseAdapter', function () { mediaType: 'banner', netRevenue: NET_REVENUE, ttl: TTL, + adhese: { + originData: { + seatbid: [ + { + bid: [ { crid: '60613369', dealid: null } ], + seat: '958' + } + ] + } + } }]; expect(spec.interpretResponse(sspBannerResponse, bidRequest)).to.deep.equal(expectedResponse); }); @@ -185,6 +195,7 @@ describe('AdheseAdapter', function () { mediaType: 'video', netRevenue: NET_REVENUE, ttl: TTL, + adhese: { originData: {} } }]; expect(spec.interpretResponse(sspVideoResponse, bidRequest)).to.deep.equal(expectedResponse); }); @@ -235,6 +246,17 @@ describe('AdheseAdapter', function () { let expectedResponse = [{ requestId: BID_ID, ad: '', + adhese: { + originData: { + adFormat: 'largeleaderboard', + adType: 'largeleaderboard', + adspaceId: '162363', + libId: '90511', + orderProperty: undefined, + priority: undefined, + viewableImpressionCounter: undefined + } + }, cpm: 5.96, currency: 'USD', creativeId: '742898', @@ -279,6 +301,17 @@ describe('AdheseAdapter', function () { let expectedResponse = [{ requestId: BID_ID, vastXml: '', + adhese: { + originData: { + adFormat: '', + adType: 'preroll', + adspaceId: '164196', + libId: '89860', + orderProperty: undefined, + priority: undefined, + viewableImpressionCounter: undefined + } + }, cpm: 0, currency: 'USD', creativeId: '742470', From 1443e4cdf59b3b5f50deb89b6157d3a395108b3c Mon Sep 17 00:00:00 2001 From: DeepthiNeeladri Date: Thu, 28 Nov 2019 15:05:09 +0530 Subject: [PATCH 432/436] BugFix: Site id missing (#4467) * outstream changes * removing global filtet * reverting page * message * adapter change * remove space * testcases * testpage * spaces for test page * renderer exist case * reverting package-lock.json * adding schain object * adding tagid * syntaxx error fix * video.html * space trailing * space * tagid * inventoryId and placement * rewarded video * added unit test case * adding site id * adding placement and siteis * site id param test case * removing deprecated functions * correcting test cases * indentation * test cases fix --- modules/oneVideoBidAdapter.js | 17 ++++--- test/spec/modules/oneVideoBidAdapter_spec.js | 53 +++++++++++++++----- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 6243bf0497e..7e8bd3ad288 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -48,7 +48,7 @@ export const spec = { /** removing adding local protocal since we * can get cookie data only if we call with https. */ url: spec.ENDPOINT + bid.params.pubId, - data: getRequestData(bid, consentData), + data: getRequestData(bid, consentData, bidRequest), bidRequest: bid } }) @@ -138,10 +138,10 @@ function isConsentRequired(consentData) { return !!(consentData && consentData.gdprApplies); } -function getRequestData(bid, consentData) { - let loc = utils.getTopWindowLocation(); +function getRequestData(bid, consentData, bidRequest) { + let loc = bidRequest.refererInfo.referer; let page = (bid.params.site && bid.params.site.page) ? (bid.params.site.page) : (loc.href); - let ref = (bid.params.site && bid.params.site.referrer) ? bid.params.site.referrer : utils.getTopWindowReferrer(); + let ref = (bid.params.site && bid.params.site.referrer) ? bid.params.site.referrer : bidRequest.refererInfo.referer; let bidData = { id: utils.generateUUID(), at: 2, @@ -198,9 +198,6 @@ function getRequestData(bid, consentData) { if (bid.params.video.rewarded) { bidData.imp[0].ext.rewarded = bid.params.video.rewarded } - if (bid.params.site && bid.params.site.id) { - bidData.site.id = bid.params.site.id - } } else if (bid.params.video.display == 1) { bidData.imp[0].banner = { mimes: bid.params.video.mimes, @@ -208,6 +205,9 @@ function getRequestData(bid, consentData) { h: bid.params.video.playerHeight, pos: bid.params.video.position, }; + if (bid.params.video.placement) { + bidData.imp[0].banner.placement = bid.params.video.placement + } } if (bid.params.video.inventoryid) { bidData.imp[0].ext.inventoryid = bid.params.video.inventoryid @@ -225,6 +225,9 @@ function getRequestData(bid, consentData) { } } } + if (bid.params.site && bid.params.site.id) { + bidData.site.id = bid.params.site.id + } if (isConsentRequired(consentData)) { bidData.regs = { ext: { diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index eccfda0cef7..d46bba038b2 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -5,7 +5,21 @@ import {config} from 'src/config'; describe('OneVideoBidAdapter', function () { let bidRequest; - let bidderRequest; + let bidderRequest = { + 'bidderCode': 'oneVideo', + 'auctionId': 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4', + 'bidderRequestId': '1e498b84fffc39', + 'bids': bidRequest, + 'auctionStart': 1520001292880, + 'timeout': 3000, + 'start': 1520001292884, + 'doneCbCallCount': 0, + 'refererInfo': { + 'numIframes': 1, + 'reachedTop': true, + 'referer': 'test.com' + } + }; let mockConfig; beforeEach(function () { @@ -105,18 +119,18 @@ describe('OneVideoBidAdapter', function () { describe('spec.buildRequests', function () { it('should create a POST request for every bid', function () { - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(spec.ENDPOINT + bidRequest.params.pubId); }); it('should attach the bid request object', function () { - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); expect(requests[0].bidRequest).to.equal(bidRequest); }); it('should attach request data', function () { - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; const placement = bidRequest.params.video.placement; @@ -134,7 +148,7 @@ describe('OneVideoBidAdapter', function () { const width = 640; const height = 480; bidRequest.sizes = [[ width, height ]]; - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; expect(data.imp[0].video.w).to.equal(width); expect(data.imp[0].video.h).to.equal(height); @@ -185,9 +199,22 @@ describe('OneVideoBidAdapter', function () { describe('when GDPR applies', function () { beforeEach(function () { bidderRequest = { - gdprConsent: { - consentString: 'test-gdpr-consent-string', - gdprApplies: true + 'gdprConsent': { + 'consentString': 'test-gdpr-consent-string', + 'gdprApplies': true + }, + 'bidderCode': 'oneVideo', + 'auctionId': 'e158486f-8c7f-472f-94ce-b0cbfbb50ab4', + 'bidderRequestId': '1e498b84fffc39', + 'bids': bidRequest, + 'auctionStart': 1520001292880, + 'timeout': 3000, + 'start': 1520001292884, + 'doneCbCallCount': 0, + 'refererInfo': { + 'numIframes': 1, + 'reachedTop': true, + 'referer': 'test.com' } }; @@ -211,7 +238,7 @@ describe('OneVideoBidAdapter', function () { }); it('should send schain object', function () { - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; expect(data.source.ext.schain.nodes[0].sid).to.equal(bidRequest.params.video.sid); expect(data.source.ext.schain.nodes[0].rid).to.equal(data.id); @@ -253,7 +280,7 @@ describe('OneVideoBidAdapter', function () { pubId: 'OneMDisplay' } }; - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; const width = bidRequest.params.video.playerWidth; const height = bidRequest.params.video.playerHeight; @@ -264,6 +291,8 @@ describe('OneVideoBidAdapter', function () { expect(data.imp[0].banner.pos).to.equal(position); expect(data.imp[0].ext.inventoryid).to.equal(bidRequest.params.video.inventoryid); expect(data.imp[0].banner.mimes).to.equal(bidRequest.params.video.mimes); + expect(data.imp[0].banner.placement).to.equal(bidRequest.params.video.placement); + expect(data.site.id).to.equal(bidRequest.params.site.id); }); it('should send video object when display is other than 1', function () { bidRequest = { @@ -299,7 +328,7 @@ describe('OneVideoBidAdapter', function () { pubId: 'OneMDisplay' } }; - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; const width = bidRequest.params.video.playerWidth; const height = bidRequest.params.video.playerHeight; @@ -343,7 +372,7 @@ describe('OneVideoBidAdapter', function () { pubId: 'OneMDisplay' } }; - const requests = spec.buildRequests([ bidRequest ]); + const requests = spec.buildRequests([ bidRequest ], bidderRequest); const data = requests[0].data; const width = bidRequest.params.video.playerWidth; const height = bidRequest.params.video.playerHeight; From 8e352983fc6fcbe142b2644c0a30bf7f9d883cbd Mon Sep 17 00:00:00 2001 From: sa1omon Date: Sun, 22 Dec 2019 20:47:05 +0200 Subject: [PATCH 433/436] Add support for CCPA and schain. --- modules/gamoshiBidAdapter.js | 71 ++- test/spec/modules/gamoshiBidAdapter_spec.js | 461 ++++++++++---------- 2 files changed, 277 insertions(+), 255 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 92d7ece4adb..05628ca2a76 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -77,9 +77,9 @@ export const spec = { }, imp: [], ext: {}, - user: { - ext: {} - } + user: {ext: {}}, + source: {ext: {}}, + regs: {ext: {}} }; const gdprConsent = bidderRequest.gdprConsent; @@ -88,17 +88,20 @@ export const spec = { consent_string: gdprConsent.consentString, consent_required: gdprConsent.gdprApplies }; - rtbBidRequest.regs = { - ext: { - gdpr: gdprConsent.gdprApplies === true ? 1 : 0 - } - }; - rtbBidRequest.user = { - ext: { - consent: gdprConsent.consentString - } - } + + utils.deepSetValue(rtbBidRequest, 'regs.ext.gdpr', gdprConsent.gdprApplies === true ? 1 : 0); + utils.deepSetValue(rtbBidRequest, 'user.ext.consent', gdprConsent.consentString); + } + + if (validBidRequests[0].schain) { + console.log('schain was found: ', validBidRequests[0].schain); + utils.deepSetValue(rtbBidRequest, 'source.ext.schain', validBidRequests[0].schain); + } + + if (bidderRequest && bidderRequest.uspConsent) { + utils.deepSetValue(rtbBidRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } + const imp = { id: transactionId, instl: params.instl === 1 ? 1 : 0, @@ -166,7 +169,12 @@ export const spec = { return; } - return {method: 'POST', url: rtbEndpoint, data: rtbBidRequest, bidRequest}; + return { + method: 'POST', + url: rtbEndpoint, + data: rtbBidRequest, + bidRequest + }; }); }, @@ -209,28 +217,34 @@ export const spec = { return outBids; }, - getUserSyncs: function (syncOptions, serverResponses, gdprConsent) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { const syncs = []; const gdprApplies = gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; const suffix = gdprApplies ? 'gc=' + encodeURIComponent(gdprConsent.consentString) : 'gc=missing'; + serverResponses.forEach(resp => { if (resp.body) { const bidResponse = resp.body; if (bidResponse.ext && Array.isArray(bidResponse.ext['utrk'])) { - bidResponse.ext['utrk'].forEach(pixel => { - const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - return syncs.push({type: pixel.type, url}); - }); + bidResponse.ext['utrk'] + .forEach(pixel => { + const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); + if (url.indexOf('')) { + return syncs.push({type: pixel.type, url}); + } + }); } + if (Array.isArray(bidResponse.seatbid)) { bidResponse.seatbid.forEach(seatBid => { if (Array.isArray(seatBid.bid)) { seatBid.bid.forEach(bid => { if (bid.ext && Array.isArray(bid.ext['utrk'])) { - bid.ext['utrk'].forEach(pixel => { - const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - return syncs.push({type: pixel.type, url}); - }); + bid.ext['utrk'] + .forEach(pixel => { + const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); + return syncs.push({type: pixel.type, url}); + }); } }); } @@ -238,6 +252,17 @@ export const spec = { } } }); + + const gdpr = gdprApplies ? 1 : 0; + const consentString = gdprApplies && gdprConsent.consent_string ? gdprConsent.consent_string : ''; + const uspConsentString = uspConsent || ''; + + syncs.forEach((syncData) => { + syncData.url = syncData.url + .replace('[GDPR]', gdpr) + .replace('[CONSENT]', consentString) + .replace('[US_PRIVACY]', uspConsentString); + }); return syncs; } }; diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index a0e569a905f..d729fa786d1 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -5,35 +5,227 @@ import {newBidder} from '../../../src/adapters/bidderFactory'; const supplyPartnerId = '123'; const adapter = newBidder(spec); -describe('GamoshiAdapter', function () { - describe('Get top Frame', function () { - it('check if you are in the top frame', function () { +const TTL = 360; + +describe('GamoshiAdapter', () => { + let schainConfig, + bidRequest, + bannerBidRequest, + videoBidRequest, + rtbResponse, + videoResponse, + gdprConsent; + + beforeEach(() => { + schainConfig = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + } + ] + }; + + bidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': '1d1a030790a475', + 'mediaTypes': { + banner: {} + }, + 'params': { + 'supplyPartnerId': supplyPartnerId + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': 'a123456789', + refererInfo: {referer: 'http://examplereferer.com'}, + gdprConsent: { + consentString: 'some string', + gdprApplies: true + }, + schain: schainConfig, + uspConsent: 'gamoshiCCPA' + }; + + bannerBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': '1d1a030790a475', + 'mediaTypes': { + banner: {} + }, + 'params': { + 'supplyPartnerId': supplyPartnerId + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': 'a123456789', + 'bidId': '111', + refererInfo: {referer: 'http://examplereferer.com'} + }; + + videoBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': '1d1a030790a475', + 'mediaTypes': { + video: {} + }, + 'params': { + 'supplyPartnerId': supplyPartnerId + }, + 'sizes': [[300, 250], [300, 600]], + 'transactionId': 'a123456789', + 'bidId': '111', + refererInfo: {referer: 'http://examplereferer.com'} + }; + + rtbResponse = { + 'id': 'imp_5b05b9fde4b09084267a556f', + 'bidid': 'imp_5b05b9fde4b09084267a556f', + 'cur': 'USD', + 'ext': { + 'utrk': [ + {'type': 'iframe', 'url': '//rtb.gamoshi.io/user/sync/1'}, + {'type': 'image', 'url': '//rtb.gamoshi.io/user/sync/2'} + ] + }, + 'seatbid': [ + { + 'seat': 'seat1', + 'group': 0, + 'bid': [ + { + 'id': '0', + 'impid': '1', + 'price': 2.016, + 'adid': '579ef31bfa788b9d2000d562', + 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0', + 'adm': '', + 'adomain': ['aaa.com'], + 'cid': '579ef268fa788b9d2000d55c', + 'crid': '579ef31bfa788b9d2000d562', + 'attr': [], + 'h': 600, + 'w': 120, + 'ext': { + 'vast_url': 'http://my.vast.com', + 'utrk': [ + {'type': 'iframe', 'url': '//p.partner1.io/user/sync/1'} + ] + } + } + ] + }, + { + 'seat': 'seat2', + 'group': 0, + 'bid': [ + { + 'id': '1', + 'impid': '1', + 'price': 3, + 'adid': '542jlhdfd2112jnjf3x', + 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0', + 'adm': ' ', + 'adomain': ['bbb.com'], + 'cid': 'fgdlwjh2498ydjhg1', + 'crid': 'kjh34297ydh2133d', + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'utrk': [ + {'type': 'image', 'url': '//p.partner2.io/user/sync/1'} + ] + } + } + ] + } + ] + }; + + videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + + gdprConsent = { + gdprApplies: true, + consentString: 'consent string' + }; + }); + + describe('Get top Frame', () => { + it('check if you are in the top frame', () => { expect(helper.getTopFrame()).to.equal(0); }); - it('verify domain parsing', function () { + + it('verify domain parsing', () => { expect(helper.getTopWindowDomain('http://www.domain.com')).to.equal('www.domain.com'); }); }); - describe('Is String start with search ', function () { - it('check if a string started with', function () { + + describe('Is String start with search', () => { + it('check if a string started with', () => { expect(helper.startsWith('gamoshi.com', 'gamo')).to.equal(true); }); }); - describe('inherited functions', function () { - it('exists and is a function', function () { + describe('inherited functions', () => { + it('exists and is a function', () => { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', function () { - it('should validate supply-partner ID', function () { + describe('isBidRequestValid', () => { + it('should validate supply-partner ID', () => { expect(spec.isBidRequestValid({params: {}})).to.equal(false); expect(spec.isBidRequestValid({params: {supplyPartnerId: 123}})).to.equal(false); expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); }); - it('should validate RTB endpoint', function () { + it('should validate RTB endpoint', () => { expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // RTB endpoint has a default expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', rtbEndpoint: 123}})).to.equal(false); expect(spec.isBidRequestValid({ @@ -44,19 +236,19 @@ describe('GamoshiAdapter', function () { })).to.equal(true); }); - it('should validate bid floor', function () { + it('should validate bid floor', () => { expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // bidfloor has a default expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', bidfloor: '123'}})).to.equal(false); expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', bidfloor: 0.1}})).to.equal(true); }); - it('should validate adpos', function () { + it('should validate adpos', () => { expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // adpos has a default expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', adpos: '123'}})).to.equal(false); expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', adpos: 0.1}})).to.equal(true); }); - it('should validate instl', function () { + it('should validate instl', () => { expect(spec.isBidRequestValid({params: {supplyPartnerId: '123'}})).to.equal(true); // adpos has a default expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: '123'}})).to.equal(false); expect(spec.isBidRequestValid({params: {supplyPartnerId: '123', instl: -1}})).to.equal(false); @@ -66,25 +258,8 @@ describe('GamoshiAdapter', function () { }); }); - describe('buildRequests', function () { - const bidRequest = { - 'adUnitCode': 'adunit-code', - 'auctionId': '1d1a030790a475', - 'mediaTypes': { - banner: {} - }, - 'params': { - 'supplyPartnerId': supplyPartnerId - }, - 'sizes': [[300, 250], [300, 600]], - 'transactionId': 'a123456789', - refererInfo: {referer: 'http://examplereferer.com'}, - gdprConsent: { - consentString: 'some string', - gdprApplies: true - } - }; - it('returns an array', function () { + describe('buildRequests', () => { + it('returns an array', () => { let response; response = spec.buildRequests([]); expect(Array.isArray(response)).to.equal(true); @@ -99,7 +274,7 @@ describe('GamoshiAdapter', function () { expect(response.length).to.equal(2); }); - it('targets correct endpoint', function () { + it('targets correct endpoint', () => { let response; response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.method).to.equal('POST'); @@ -111,10 +286,11 @@ describe('GamoshiAdapter', function () { expect(response.url).to.match(new RegExp(`^https://rtb2\\.gamoshi\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); - it('builds request correctly', function () { + it('builds request correctly', () => { let bidRequest2 = utils.deepClone(bidRequest); bidRequest2.refererInfo.referer = 'http://www.test.com/page.html'; let response = spec.buildRequests([bidRequest], bidRequest2)[0]; + expect(response.data.site.domain).to.equal('www.test.com'); expect(response.data.site.page).to.equal('http://www.test.com/page.html'); expect(response.data.site.ref).to.equal('http://www.test.com/page.html'); @@ -124,6 +300,9 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].tagid).to.equal(bidRequest.adUnitCode); expect(response.data.imp[0].bidfloor).to.equal(0); expect(response.data.imp[0].bidfloorcur).to.equal('USD'); + expect(response.data.regs.ext.us_privacy).to.equal('gamoshiCCPA');// USP/CCPAs + expect(response.data.source.ext.schain).to.deep.equal(bidRequest2.schain); + const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; response = spec.buildRequests([bidRequestWithInstlEquals1], bidRequest2)[0]; @@ -138,7 +317,7 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); }); - it('builds request banner object correctly', function () { + it('builds request banner object correctly', () => { let response; const bidRequestWithBanner = utils.deepClone(bidRequest); bidRequestWithBanner.mediaTypes = { @@ -157,7 +336,7 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); - it('builds request video object correctly', function () { + it('builds request video object correctly', () => { let response; const bidRequestWithVideo = utils.deepClone(bidRequest); bidRequestWithVideo.mediaTypes = { @@ -184,15 +363,14 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); - it('builds request video object correctly with context', function () { - let response; + it('builds request video object correctly with context', () => { const bidRequestWithVideo = utils.deepClone(bidRequest); bidRequestWithVideo.mediaTypes = { video: { context: 'instream' } }; - response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + let response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; expect(response.data.imp[0].video.ext.context).to.equal('instream'); bidRequestWithVideo.mediaTypes.video.context = 'outstream'; @@ -207,7 +385,7 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].video.ext.context).to.equal(null); }); - it('builds request video object correctly with multi-dimensions size array', function () { + it('builds request video object correctly with multi-dimensions size array', () => { let response; const bidRequestWithVideo = utils.deepClone(bidRequest); bidRequestWithVideo.mediaTypes.video = { @@ -230,7 +408,7 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[1].video.ext.context).to.equal(null); }); - it('builds request with gdpr consent', function () { + it('builds request with gdpr consent', () => { let response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.data.ext.gdpr_consent).to.not.equal(null).and.not.equal(undefined); @@ -242,7 +420,7 @@ describe('GamoshiAdapter', function () { expect(response.data.user.ext.consent).to.equal('some string'); }); - it('build request with ID5 Id', function () { + it('build request with ID5 Id', () => { const bidRequestClone = utils.deepClone(bidRequest); bidRequestClone.userId = {}; bidRequestClone.userId.id5id = 'id5-user-id'; @@ -258,7 +436,7 @@ describe('GamoshiAdapter', function () { }]); }); - it('build request with unified Id', function () { + it('build request with unified Id', () => { const bidRequestClone = utils.deepClone(bidRequest); bidRequestClone.userId = {}; bidRequestClone.userId.tdid = 'tdid-user-id'; @@ -276,107 +454,8 @@ describe('GamoshiAdapter', function () { }); describe('interpretResponse', () => { - const bannerBidRequest = { - 'adUnitCode': 'adunit-code', - 'auctionId': '1d1a030790a475', - 'mediaTypes': { - banner: {} - }, - 'params': { - 'supplyPartnerId': supplyPartnerId - }, - 'sizes': [[300, 250], [300, 600]], - 'transactionId': 'a123456789', - 'bidId': '111', - refererInfo: {referer: 'http://examplereferer.com'} - }; - - const videoBidRequest = { - 'adUnitCode': 'adunit-code', - 'auctionId': '1d1a030790a475', - 'mediaTypes': { - video: {} - }, - 'params': { - 'supplyPartnerId': supplyPartnerId - }, - 'sizes': [[300, 250], [300, 600]], - 'transactionId': 'a123456789', - 'bidId': '111', - refererInfo: {referer: 'http://examplereferer.com'} - }; - - const rtbResponse = { - 'id': 'imp_5b05b9fde4b09084267a556f', - 'bidid': 'imp_5b05b9fde4b09084267a556f', - 'cur': 'USD', - 'ext': { - 'utrk': [ - {'type': 'iframe', 'url': '//rtb.gamoshi.io/user/sync/1'}, - {'type': 'image', 'url': '//rtb.gamoshi.io/user/sync/2'} - ] - }, - 'seatbid': [ - { - 'seat': 'seat1', - 'group': 0, - 'bid': [ - { - 'id': '0', - 'impid': '1', - 'price': 2.016, - 'adid': '579ef31bfa788b9d2000d562', - 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0', - 'adm': '', - 'adomain': ['aaa.com'], - 'cid': '579ef268fa788b9d2000d55c', - 'crid': '579ef31bfa788b9d2000d562', - 'attr': [], - 'h': 600, - 'w': 120, - 'ext': { - 'vast_url': 'http://my.vast.com', - 'utrk': [ - {'type': 'iframe', 'url': '//p.partner1.io/user/sync/1'} - ] - } - } - ] - }, - { - 'seat': 'seat2', - 'group': 0, - 'bid': [ - { - 'id': '1', - 'impid': '1', - 'price': 3, - 'adid': '542jlhdfd2112jnjf3x', - 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0', - 'adm': ' ', - 'adomain': ['bbb.com'], - 'cid': 'fgdlwjh2498ydjhg1', - 'crid': 'kjh34297ydh2133d', - 'attr': [], - 'h': 250, - 'w': 300, - 'ext': { - 'utrk': [ - {'type': 'image', 'url': '//p.partner2.io/user/sync/1'} - ] - } - } - ] - } - ] - }; - - const TTL = 360; - - it('returns an empty array on missing response', function () { - let response; - - response = spec.interpretResponse(undefined, {bidRequest: bannerBidRequest}); + it('returns an empty array on missing response', () => { + let response = spec.interpretResponse(undefined, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); @@ -385,7 +464,7 @@ describe('GamoshiAdapter', function () { expect(response.length).to.equal(0); }); - it('aggregates banner bids from all seat bids', function () { + it('aggregates banner bids from all seat bids', () => { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); @@ -403,7 +482,7 @@ describe('GamoshiAdapter', function () { expect(ad0.vastUrl).to.be.an('undefined'); }); - it('aggregates video bids from all seat bids', function () { + it('aggregates video bids from all seat bids', () => { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); @@ -421,7 +500,7 @@ describe('GamoshiAdapter', function () { expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); }); - it('aggregates user-sync pixels', function () { + it('aggregates user-sync pixels', () => { const response = spec.getUserSyncs({}, [{body: rtbResponse}]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(4); @@ -435,96 +514,14 @@ describe('GamoshiAdapter', function () { expect(response[3].url).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].url + '?gc=missing'); }); - it('supports configuring outstream renderers', function () { - const videoResponse = { - 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', - 'bidid': 'imp_5c24924de4b0d106447af333', - 'cur': 'USD', - 'seatbid': [ - { - 'seat': '3668', - 'group': 0, - 'bid': [ - { - 'id': 'gb_1', - 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', - 'price': 5.0, - 'adid': '1274', - 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1', - 'adomain': [], - 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', - 'cid': '3668', - 'crid': '1274', - 'cat': [], - 'attr': [], - 'h': 250, - 'w': 300, - 'ext': { - 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', - 'imptrackers': [ - 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] - } - } - ] - } - ], - 'ext': { - 'utrk': [{ - 'type': 'image', - 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' - }] - } - }; + it('supports configuring outstream renderers', () => { const videoRequest = utils.deepClone(videoBidRequest); videoRequest.mediaTypes.video.context = 'outstream'; const result = spec.interpretResponse({body: videoResponse}, {bidRequest: videoRequest}); expect(result[0].renderer).to.not.equal(undefined); }); - it('validates in/existing of gdpr consent', function () { - let videoResponse = { - 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', - 'bidid': 'imp_5c24924de4b0d106447af333', - 'cur': 'USD', - 'seatbid': [ - { - 'seat': '3668', - 'group': 0, - 'bid': [ - { - 'id': 'gb_1', - 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', - 'price': 5.0, - 'adid': '1274', - 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1', - 'adomain': [], - 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', - 'cid': '3668', - 'crid': '1274', - 'cat': [], - 'attr': [], - 'h': 250, - 'w': 300, - 'ext': { - 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', - 'imptrackers': [ - 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] - } - } - ] - } - ], - 'ext': { - 'utrk': [{ - 'type': 'image', - 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' - }] - } - }; - let gdprConsent = { - gdprApplies: true, - consentString: 'consent string' - }; + it('validates in/existing of gdpr consent', () => { let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); expect(result).to.be.an('array'); expect(result.length).to.equal(1); From e897d2b696e97cdd4e829a48c4df1c8201250d8b Mon Sep 17 00:00:00 2001 From: sa1omon Date: Sun, 22 Dec 2019 20:52:26 +0200 Subject: [PATCH 434/436] Add tests for CCPA and schain. --- modules/gamoshiBidAdapter.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 05628ca2a76..c8e6d46fc5f 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -94,7 +94,6 @@ export const spec = { } if (validBidRequests[0].schain) { - console.log('schain was found: ', validBidRequests[0].schain); utils.deepSetValue(rtbBidRequest, 'source.ext.schain', validBidRequests[0].schain); } @@ -229,9 +228,7 @@ export const spec = { bidResponse.ext['utrk'] .forEach(pixel => { const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); - if (url.indexOf('')) { - return syncs.push({type: pixel.type, url}); - } + return syncs.push({type: pixel.type, url}); }); } From 0475ee30361cc264b866577afe61526f47a16b3b Mon Sep 17 00:00:00 2001 From: sa1omon Date: Mon, 23 Dec 2019 13:17:47 +0200 Subject: [PATCH 435/436] Remove suffix from url. Add unit tests. --- modules/gamoshiBidAdapter.js | 45 ++++++++++++++------- test/spec/modules/gamoshiBidAdapter_spec.js | 37 ++++++++++++----- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index c8e6d46fc5f..9bfbdaf6ad9 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -218,8 +218,28 @@ export const spec = { getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { const syncs = []; - const gdprApplies = gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean') ? gdprConsent.gdprApplies : false; - const suffix = gdprApplies ? 'gc=' + encodeURIComponent(gdprConsent.consentString) : 'gc=missing'; + let gdprApplies = false; + let consentString = ''; + let uspConsentString = ''; + + if (gdprConsent && (typeof gdprConsent.gdprApplies === 'boolean')) { + gdprApplies = gdprConsent.gdprApplies; + } + let gdpr = gdprApplies ? 1 : 0; + + if (gdprApplies && gdprConsent.consentString) { + consentString = encodeURIComponent(gdprConsent.consentString) + } + + if (uspConsent) { + uspConsentString = encodeURIComponent(uspConsent); + } + + const macros = { + gdpr: gdpr, + consent: consentString, + uspConsent: uspConsentString + }; serverResponses.forEach(resp => { if (resp.body) { @@ -227,7 +247,7 @@ export const spec = { if (bidResponse.ext && Array.isArray(bidResponse.ext['utrk'])) { bidResponse.ext['utrk'] .forEach(pixel => { - const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); + const url = replaceMacros(pixel.url, macros); return syncs.push({type: pixel.type, url}); }); } @@ -239,7 +259,7 @@ export const spec = { if (bid.ext && Array.isArray(bid.ext['utrk'])) { bid.ext['utrk'] .forEach(pixel => { - const url = pixel.url + (pixel.url.indexOf('?') > 0 ? '&' + suffix : '?' + suffix); + const url = replaceMacros(pixel.url, macros); return syncs.push({type: pixel.type, url}); }); } @@ -250,16 +270,6 @@ export const spec = { } }); - const gdpr = gdprApplies ? 1 : 0; - const consentString = gdprApplies && gdprConsent.consent_string ? gdprConsent.consent_string : ''; - const uspConsentString = uspConsent || ''; - - syncs.forEach((syncData) => { - syncData.url = syncData.url - .replace('[GDPR]', gdpr) - .replace('[CONSENT]', consentString) - .replace('[US_PRIVACY]', uspConsentString); - }); return syncs; } }; @@ -312,4 +322,11 @@ function addExternalUserId(eids, value, source, rtiPartner) { } } +function replaceMacros(url, macros) { + return url + .replace('[GDPR]', macros.gdpr) + .replace('[CONSENT]', macros.consent) + .replace('[US_PRIVACY]', macros.uspConsent); +} + registerBidder(spec); diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index d729fa786d1..003d6887ff8 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -91,7 +91,7 @@ describe('GamoshiAdapter', () => { 'cur': 'USD', 'ext': { 'utrk': [ - {'type': 'iframe', 'url': '//rtb.gamoshi.io/user/sync/1'}, + {'type': 'iframe', 'url': '//rtb.gamoshi.io/user/sync/1?gdpr=[GDPR]&consent=[CONSENT]&usp=[US_PRIVACY]'}, {'type': 'image', 'url': '//rtb.gamoshi.io/user/sync/2'} ] }, @@ -185,7 +185,7 @@ describe('GamoshiAdapter', () => { 'ext': { 'utrk': [{ 'type': 'image', - 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gdpr=[GDPR]&consent=[CONSENT]&us_privacy=[US_PRIVACY]' }] } }; @@ -505,13 +505,13 @@ describe('GamoshiAdapter', () => { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(4); expect(response[0].type).to.equal(rtbResponse.ext.utrk[0].type); - expect(response[0].url).to.equal(rtbResponse.ext.utrk[0].url + '?gc=missing'); + expect(response[0].url).to.equal('//rtb.gamoshi.io/user/sync/1?gdpr=0&consent=&usp='); expect(response[1].type).to.equal(rtbResponse.ext.utrk[1].type); - expect(response[1].url).to.equal(rtbResponse.ext.utrk[1].url + '?gc=missing'); + expect(response[1].url).to.equal('//rtb.gamoshi.io/user/sync/2'); expect(response[2].type).to.equal(rtbResponse.seatbid[0].bid[0].ext.utrk[0].type); - expect(response[2].url).to.equal(rtbResponse.seatbid[0].bid[0].ext.utrk[0].url + '?gc=missing'); + expect(response[2].url).to.equal('//p.partner1.io/user/sync/1'); expect(response[3].type).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].type); - expect(response[3].url).to.equal(rtbResponse.seatbid[1].bid[0].ext.utrk[0].url + '?gc=missing'); + expect(response[3].url).to.equal('//p.partner2.io/user/sync/1'); }); it('supports configuring outstream renderers', () => { @@ -522,25 +522,40 @@ describe('GamoshiAdapter', () => { }); it('validates in/existing of gdpr consent', () => { - let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent, 'gamoshiCCPA'); expect(result).to.be.an('array'); expect(result.length).to.equal(1); expect(result[0].type).to.equal('image'); - expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=consent%20string'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gdpr=1&consent=consent%20string&us_privacy=gamoshiCCPA'); gdprConsent.gdprApplies = false; - result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent, 'gamoshiCCPA'); expect(result).to.be.an('array'); expect(result.length).to.equal(1); expect(result[0].type).to.equal('image'); - expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=missing'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gdpr=0&consent=&us_privacy=gamoshiCCPA'); videoResponse.ext.utrk[0].url = 'https://rtb.gamoshi.io/pix/1275/scm'; result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); expect(result).to.be.an('array'); expect(result.length).to.equal(1); expect(result[0].type).to.equal('image'); - expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?gc=missing'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm'); + }); + + it('validates existence of gdpr, gdpr consent and usp consent', () => { + let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent, 'gamoshiCCPA'); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gdpr=1&consent=consent%20string&us_privacy=gamoshiCCPA'); + + gdprConsent.gdprApplies = false; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent, ''); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gdpr=0&consent=&us_privacy='); }); }); }); From 76155f3a02fc20a8568a5b6bbf652ab33315dc0f Mon Sep 17 00:00:00 2001 From: sa1omon Date: Mon, 23 Dec 2019 13:35:33 +0200 Subject: [PATCH 436/436] Change variable name. Remove unnecessary 'return' command. --- modules/gamoshiBidAdapter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 9bfbdaf6ad9..9e119d9d490 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -235,7 +235,7 @@ export const spec = { uspConsentString = encodeURIComponent(uspConsent); } - const macros = { + const macroValues = { gdpr: gdpr, consent: consentString, uspConsent: uspConsentString @@ -247,8 +247,8 @@ export const spec = { if (bidResponse.ext && Array.isArray(bidResponse.ext['utrk'])) { bidResponse.ext['utrk'] .forEach(pixel => { - const url = replaceMacros(pixel.url, macros); - return syncs.push({type: pixel.type, url}); + const url = replaceMacros(pixel.url, macroValues); + syncs.push({type: pixel.type, url}); }); } @@ -259,8 +259,8 @@ export const spec = { if (bid.ext && Array.isArray(bid.ext['utrk'])) { bid.ext['utrk'] .forEach(pixel => { - const url = replaceMacros(pixel.url, macros); - return syncs.push({type: pixel.type, url}); + const url = replaceMacros(pixel.url, macroValues); + syncs.push({type: pixel.type, url}); }); } });