Skip to content

Commit

Permalink
pre1api module that allows use of deprecated pre1.0 API in Prebid 1.0 (
Browse files Browse the repository at this point in the history
…prebid#1976)

* initial version of pre1api module to allow use of deprecated API in 1.0

* move cbTimeout to config rather than auction properties

* fix bug in auction queueing for pre-1.0 api module

* updated doc comment for pre-1.0 api module

* set next function correctly if requestBids is called w/ no arguments
  • Loading branch information
snapwich authored and Matt Kendall committed Jan 23, 2018
1 parent 6cfaa5c commit e4eee81
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 4 deletions.
156 changes: 156 additions & 0 deletions modules/pre1api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@

/**
pre1api module
This module supports backwards compatibility for those who need extra time to re-code their pages to work with the
Prebid 1.0 API. Use of this backwards compatibility module is recommended only as an interim solution.
It provides equivalents for the following variables and functions that were deprecated in PBJS 1.0:
- pbjs._winningBids
- pbjs._bidsReceived
- pbjs._bidsRequested
- pbjs._adUnitCodes
- pbjs._adsReceived
- pbjs.cbTimeout
- pbjs.addCallback()
- pbjs.removeCallback()
- pbjs.allBidsAvailable()
- pbjs.bidderTimeout
- pbjs.logging
- pbjs.publisherDomain
- pbjs.setPriceGranularity()
- pbjs.enableSendAllBids() // and also defaults this value to `false` like pre-1.0
- pbjs.setBidderSequence()
- pbjs.setS2SConfig() // and makes endpoints optional again (defaulting to the appnexus endpoints)
This will not support the pre-1.0 sizeMapping feature.
The drawback is that this module disables concurrency for requestBids(), queueing them as was done in pre-1.0. Anytime
an auction request is queued or one of these APIs is accessed it will display a deprecation warning in the console if
logging is enabled. So while this is useful for those that need more time to migrate, it eliminates one of the best
features of PBJS 1.0 as is required to emulate the old API.
*/

import {config} from 'src/config';
import {logWarn, logInfo} from 'src/utils';

const MODULE_NAME = 'pre-1.0 API';

let pbjs = window['$$PREBID_GLOBAL$$'];

logInfo(`loading ${MODULE_NAME} module and patching prebid with deprecated APIs.`);

let auctionQueue = [];

let emptyFn = () => [];

Object.defineProperty(pbjs, '_winningBids', {
get: () => pbjs.getAllWinningBids()
});

let auctionPropMap = {
_bidsReceived: auction => auction.getBidsReceived(),
_bidsRequested: auction => auction.getBidRequests(),
_adUnitCodes: auction => auction.getAdUnitCodes(),
allBidsAvailable: auction => auction.getBidRequests().every((bidRequest) => bidRequest.doneCbCallCount >= 1)
};

let configPropMap = {
cbTimeout: 'bidderTimeout',
bidderTimeout: 'bidderTimeout',
logging: 'debug',
publisherDomain: 'publisherDomain',
enableSendAllBids: 'enableSendAllBids',
setPriceGranularity: 'priceGranularity',
setBidderSequence: 'bidderSequence',
setS2SConfig: 's2sConfig'
};

pbjs.addCallback = pbjs.onEvent;
pbjs.removeCallback = pbjs.offEvent;

// can't see anywhere that this was used, but it is listed in Prebid 1.0 transition guide...
// so just adding as empty array
pbjs._adsReceived = [];

config.setDefaults({
enableSendAllBids: false,
cache: {
url: 'https://prebid.adnxs.com/pbc/v1/cache'
}
});

let currAuction = {
getBidsReceived: emptyFn,
getBidsRequested: emptyFn,
getAdUnitCodes: emptyFn,
getTimeout: () => config.getConfig('bidderTimeout')
};

// we need to intercept s2sConfig rather than call setConfig or setDefaults directly, otherwise the code will fail when
// the server adapter attempts to validate the configuration passed in by the publisher
config.setConfig.addHook((config, next) => {
if (config.s2sConfig) {
config.s2sConfig = Object.assign({
endpoint: 'https://prebid.adnxs.com/pbs/v1/auction',
syncEndpoint: 'https://prebid.adnxs.com/pbs/v1/cookie_sync'
}, config.s2sConfig);
}
next(config);
});

/**
* Hook to queue and disallow concurrent auctions (as Prebid would function pre 1.0)
*/
pbjs.requestBids.addHook((config, next = config) => {
auctionQueue.push(() => {
let oldHandler = config.bidsBackHandler;
config.bidsBackHandler = (...args) => {
if (typeof oldHandler === 'function') {
oldHandler.apply(null, args);
}

auctionQueue.shift();
if (auctionQueue[0]) {
auctionQueue[0]();
}
};

currAuction = next(config);
});

if (auctionQueue.length === 1) {
auctionQueue[0]();
} else {
logWarn(`${MODULE_NAME} module: concurrency has been disabled and "$$PREBID_GLOBAL$$.requestBids" call was queued`);
}
}, 100);

Object.keys(auctionPropMap).forEach(prop => {
if (prop === 'allBidsAvailable') {
pbjs[prop] = deprecated(prop, () => auctionPropMap[prop](currAuction));
}
Object.defineProperty(pbjs, prop, {
get: deprecated(prop, () => auctionPropMap[prop](currAuction))
});
});

Object.keys(configPropMap).forEach(prop => {
if (prop === 'enableSendAllBids') {
pbjs[prop] = deprecated(prop, () => config.setConfig({[prop]: true}));
} else if (prop.lastIndexOf('set', 0) === 0) {
pbjs[prop] = deprecated(prop, value => config.setConfig({[configPropMap[prop]]: value}));
} else {
Object.defineProperty(pbjs, prop, {
get: deprecated(prop, () => config.getConfig(configPropMap[prop])),
set: deprecated(prop, value => config.setConfig({[configPropMap[prop]]: value}))
});
}
});

function deprecated(name, fn) {
return (...args) => {
logWarn(`${MODULE_NAME} module: accessed deprecated API "$$PREBID_GLOBAL$$.${name}"`);
return fn.apply(null, args);
};
}
5 changes: 3 additions & 2 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { isValidPriceConfig } from './cpmBucketManager';
import find from 'core-js/library/fn/array/find';
import includes from 'core-js/library/fn/array/includes';
import { createHook } from 'src/hook';
const utils = require('./utils');

const DEFAULT_DEBUG = false;
Expand Down Expand Up @@ -188,7 +189,7 @@ export function newConfig() {
* Sets configuration given an object containing key-value pairs and calls
* listeners that were added by the `subscribe` function
*/
function setConfig(options) {
let setConfig = createHook('asyncSeries', function setConfig(options) {
if (typeof options !== 'object') {
utils.logError('setConfig options must be an object');
return;
Expand All @@ -208,7 +209,7 @@ export function newConfig() {
});

callSubscribers(topicalConfig);
}
});

/**
* Sets configuration defaults which setConfig values can be applied on top of
Expand Down
6 changes: 4 additions & 2 deletions src/prebid.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { loadScript } from './adloader';
import { config } from './config';
import { auctionManager } from './auctionManager';
import { targeting } from './targeting';
import { createHook } from 'src/hook';
import includes from 'core-js/library/fn/array/includes';

var $$PREBID_GLOBAL$$ = getGlobal();
Expand Down Expand Up @@ -283,7 +284,7 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) {
* @param {Array} requestOptions.labels
* @alias module:pbjs.requestBids
*/
$$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) {
$$PREBID_GLOBAL$$.requestBids = createHook('asyncSeries', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) {
events.emit('requestBids');
const cbTimeout = timeout || config.getConfig('bidderTimeout');
adUnits = adUnits || $$PREBID_GLOBAL$$.adUnits;
Expand Down Expand Up @@ -333,7 +334,8 @@ $$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, a

const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels});
auction.callBids();
};
return auction;
});

/**
*
Expand Down

0 comments on commit e4eee81

Please sign in to comment.