<commit_before>//URL RegEx from https://gist.github.com/dperini/729294
//http://mathiasbynens.be/demo/url-regex

//@export SchemaRegEx
SchemaRegEx = {
    Email: /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/,
    Url: /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i
};

SimpleSchema = function(schema) {
    var self = this;
    self._schema = schema || {};
};

//validates doc against self._schema and returns an array of error objects
SimpleSchema.prototype.validate = function(doc) {
    var self = this, invalidFields = [];
    var isSetting = "$set" in doc;
    var isUnsetting = "$unset" in doc;

    //all fields must pass validation check
    _.each(self._schema, function(def, fieldName) {
        var fieldValue;
        var fieldLabel = def.label || fieldName;

        //first check unsetting
        if (isUnsetting && fieldName in doc.$unset) {
            fieldValue = doc.$unset[fieldName];
            if (fieldValue === void 0 || fieldValue === null || (typeof fieldValue === "string" && fieldValue.length === 0)) {
                if (!def.optional) {
                    invalidFields.push({name: fieldName, message: fieldLabel + " is required"});
                } //else it's valid, and no need to perform further checks on this field
            }
        }

        //next check setting or inserting
        if (isSetting) {
            fieldValue = doc.$set[fieldName];
        } else {
            fieldValue = doc[fieldName];
        }

        invalidFields = _.union(invalidFields, validateOne(def, fieldName, fieldLabel, fieldValue, isSetting));
    });

    return invalidFields;
};

//returns doc with all properties that are not in the schema removed
SimpleSchema.prototype.filter = function(doc) {
    //TODO make sure this works with descendent objects
    var newDoc, self = this;
    if ("$set" in doc) {
        //for $set, filter only that obj
        newDoc = doc;
        newDoc.$set = _.pick(doc.$set, _.keys(self._schema));
    } else {
        newDoc = _.pick(doc, _.keys(self._schema));
    }
    return newDoc;
};

//automatic type conversion to match desired type, if possible
SimpleSchema.prototype.autoTypeConvert = function(doc) {
    var self = this;
    _.each(self._schema, function(def, fieldName) {
        if (fieldName in doc) {
            doc[fieldName] = typeconvert(doc[fieldName], def.type); //typeconvert
        } else if ("$set" in doc && fieldName in doc.$set) {
            doc.$set[fieldName] = typeconvert(doc.$set[fieldName], def.type); //typeconvert
        }
    });
    return doc;
};

var validateOne = function(def, fieldName, fieldLabel, fieldValue, isSetting) {
    var invalidFields = [];
    //when inserting required fields, fieldValue must not be undefined, null, or an empty string
    //when updating ($setting) required fields, fieldValue can be undefined, but may not be null or an empty string
    if ((!isSetting && fieldValue === void 0) || fieldValue === null || (typeof fieldValue === "string" && fieldValue.length === 0)) {
        if (!def.optional) {
            invalidFields.push({name: fieldName, message: fieldLabel + " is required"});
        } //else it's valid, and no need to perform further checks on this field
        return invalidFields;
    }

    //if we got to this point and fieldValue is undefined, no more checking is necessary for this field
    if (fieldValue === void 0) {
        return invalidFields;
    }

    if (def.type === String) {
        if (typeof fieldValue !== "string") {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a string"});
        } else if (def.regEx && !def.regEx.test(fieldValue)) {
            invalidFields.push({name: fieldName, message: fieldLabel + " " + def.regExMessage});
        } else if (def.max && def.max < fieldValue.length) {
            invalidFields.push({name: fieldName, message: fieldLabel + " cannot exceed " + def.max + " characters"});
        } else if (def.min && def.min > fieldValue.length) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be at least " + def.min + " characters"});
        }
        return invalidFields;
    }

    if (def.type === Number) {
        if (typeof fieldValue !== "number") {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a number"});
        } else if (def.max && def.max < fieldValue) {
            invalidFields.push({name: fieldName, message: fieldLabel + " cannot exceed " + def.max});
        } else if (def.min && def.min > fieldValue) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be at least " + def.min});
        } else if (!def.decimal && fieldValue.toString().indexOf(".") > -1) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be an integer"});
        }
        return invalidFields;
    }

    if (def.type === Boolean) {
        if (typeof fieldValue !== "boolean") {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a boolean"});
        }
        return invalidFields;
    }

    if (def.type instanceof Function) {
        if (!(fieldValue instanceof def.type)) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a " + def.type.name});
        }
        if (def.type === Date) {
            if (_.isDate(def.min) && def.min.getTime() > fieldValue.getTime()) {
                invalidFields.push({name: fieldName, message: fieldLabel + " must be on or after " + dateToFieldDateString(def.min)});
            } else if (_.isDate(def.max) && def.max.getTime() < fieldValue.getTime()) {
                invalidFields.push({name: fieldName, message: fieldLabel + " must be on or before " + dateToFieldDateString(def.max)});
            }
        }
        return invalidFields;
    }

    //if it's an array, loop through it and call validateOne recursively
    if (_.isArray(def.type)) {
        if (!_.isArray(fieldValue)) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be an array"});
        } else if (def.min && fieldValue.length < def.min) {
            invalidFields.push({name: fieldName, message: "You must specify at least " + def.min + " values"});
        } else if (def.max && fieldValue.length > def.max) {
            invalidFields.push({name: fieldName, message: "You cannot specify more than " + def.max + " values"});
        } else {
            //if it's an array with the right number of values, etc., then we need to go through them all and
            //validate each value in the array
            var childDef = def, loopVal;
            childDef.type = def.type[0]; //strip array off of type
            //min and max only apply to the array
            if ("min" in childDef) {
                delete childDef.min;
            }
            if ("max" in childDef) {
                delete childDef.max;
            }
            for (var i = 0, ln = fieldValue.length; i < ln; i++) {
                loopVal = fieldValue[i];
                invalidFields = _.union(invalidFields, validateOne(childDef, fieldName, fieldLabel, loopVal, isSetting));
                if (invalidFields.length) {
                    break;
                }
                //while we're looping through, also check to make sure this value is allowed
                if (def.allowedValues) {
                    if (!_.contains(def.allowedValues, loopVal)) {
                        invalidFields.push({name: fieldName, message: loopVal + " is not an allowed value"});
                    }
                } else if (def.valueIsAllowed && def.valueIsAllowed instanceof Function) {
                    if (!def.valueIsAllowed(loopVal)) {
                        invalidFields.push({name: fieldName, message: loopVal + " is not an allowed value"});
                    }
                }
                if (invalidFields.length) {
                    break;
                }
            }
        }
        return invalidFields;
    }
};

var dateToFieldDateString = function(date) {
    var m = (date.getUTCMonth() + 1);
    if (m < 10) {
        m = "0" + m;
    }
    var d = date.getUTCDate();
    if (d < 10) {
        d = "0" + d;
    }
    return date.getUTCFullYear() + '-' + m + '-' + d;
};

var typeconvert = function(value, type) {
    if (type === String) {
        if (typeof value !== "string") {
            return value.toString();
        }
        return value;
    }
    if (type === Number) {
        if (typeof value === "string") {
            //try to convert numeric strings to numbers
            var floatVal = parseFloat(value);
            if (!isNaN(floatVal)) {
                return floatVal;
            } else {
                return value; //leave string; will fail validation
            }
        }
        return value;
    }
    return value;
};<commit_msg>fix array validation and allowedValue checking<commit_after>//URL RegEx from https://gist.github.com/dperini/729294
//http://mathiasbynens.be/demo/url-regex

//@export SchemaRegEx
SchemaRegEx = {
    Email: /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/,
    Url: /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i
};

SimpleSchema = function(schema) {
    var self = this;
    self._schema = schema || {};
};

//validates doc against self._schema and returns an array of error objects
SimpleSchema.prototype.validate = function(doc) {
    var self = this, invalidFields = [];
    var isSetting = "$set" in doc;
    var isUnsetting = "$unset" in doc;

    //all fields must pass validation check
    _.each(self._schema, function(def, fieldName) {
        var fieldValue;
        var fieldLabel = def.label || fieldName;

        //first check unsetting
        if (isUnsetting && fieldName in doc.$unset) {
            fieldValue = doc.$unset[fieldName];
            if (fieldValue === void 0 || fieldValue === null || (typeof fieldValue === "string" && fieldValue.length === 0)) {
                if (!def.optional) {
                    invalidFields.push({name: fieldName, message: fieldLabel + " is required"});
                } //else it's valid, and no need to perform further checks on this field
            }
        }

        //next check setting or inserting
        if (isSetting) {
            fieldValue = doc.$set[fieldName];
        } else {
            fieldValue = doc[fieldName];
        }

        invalidFields = _.union(invalidFields, validateOne(def, fieldName, fieldLabel, fieldValue, isSetting));
    });

    return invalidFields;
};

//returns doc with all properties that are not in the schema removed
SimpleSchema.prototype.filter = function(doc) {
    //TODO make sure this works with descendent objects
    var newDoc, self = this;
    if ("$set" in doc) {
        //for $set, filter only that obj
        newDoc = doc;
        newDoc.$set = _.pick(doc.$set, _.keys(self._schema));
    } else {
        newDoc = _.pick(doc, _.keys(self._schema));
    }
    return newDoc;
};

//automatic type conversion to match desired type, if possible
SimpleSchema.prototype.autoTypeConvert = function(doc) {
    var self = this;
    _.each(self._schema, function(def, fieldName) {
        if (fieldName in doc) {
            doc[fieldName] = typeconvert(doc[fieldName], def.type); //typeconvert
        } else if ("$set" in doc && fieldName in doc.$set) {
            doc.$set[fieldName] = typeconvert(doc.$set[fieldName], def.type); //typeconvert
        }
    });
    return doc;
};

var validateOne = function(def, fieldName, fieldLabel, fieldValue, isSetting) {
    var invalidFields = [];
    //when inserting required fields, fieldValue must not be undefined, null, or an empty string
    //when updating ($setting) required fields, fieldValue can be undefined, but may not be null or an empty string
    if ((!isSetting && fieldValue === void 0) || fieldValue === null || (typeof fieldValue === "string" && fieldValue.length === 0)) {
        if (!def.optional) {
            invalidFields.push({name: fieldName, message: fieldLabel + " is required"});
        } //else it's valid, and no need to perform further checks on this field
        return invalidFields;
    }

    //if we got to this point and fieldValue is undefined, no more checking is necessary for this field
    if (fieldValue === void 0) {
        return invalidFields;
    }

    if (def.type === String) {
        if (typeof fieldValue !== "string") {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a string"});
        } else if (def.regEx && !def.regEx.test(fieldValue)) {
            invalidFields.push({name: fieldName, message: fieldLabel + " " + def.regExMessage});
        } else if (def.max && def.max < fieldValue.length) {
            invalidFields.push({name: fieldName, message: fieldLabel + " cannot exceed " + def.max + " characters"});
        } else if (def.min && def.min > fieldValue.length) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be at least " + def.min + " characters"});
        }
        return invalidFields;
    }

    if (def.type === Number) {
        if (typeof fieldValue !== "number") {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a number"});
        } else if (def.max && def.max < fieldValue) {
            invalidFields.push({name: fieldName, message: fieldLabel + " cannot exceed " + def.max});
        } else if (def.min && def.min > fieldValue) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be at least " + def.min});
        } else if (!def.decimal && fieldValue.toString().indexOf(".") > -1) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be an integer"});
        }
        return invalidFields;
    }

    if (def.type === Boolean) {
        if (typeof fieldValue !== "boolean") {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a boolean"});
        }
        return invalidFields;
    }

    if (def.type instanceof Function) {
        if (!(fieldValue instanceof def.type)) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be a " + def.type.name});
        }
        if (def.type === Date) {
            if (_.isDate(def.min) && def.min.getTime() > fieldValue.getTime()) {
                invalidFields.push({name: fieldName, message: fieldLabel + " must be on or after " + dateToFieldDateString(def.min)});
            } else if (_.isDate(def.max) && def.max.getTime() < fieldValue.getTime()) {
                invalidFields.push({name: fieldName, message: fieldLabel + " must be on or before " + dateToFieldDateString(def.max)});
            }
        }
        return invalidFields;
    }

    //check to make sure the value is allowed
    if (def.allowedValues) {
        if (!_.contains(def.allowedValues, fieldValue)) {
            invalidFields.push({name: fieldName, message: loopVal + " is not an allowed value"});
        }
    } else if (def.valueIsAllowed && def.valueIsAllowed instanceof Function) {
        if (!def.valueIsAllowed(fieldValue)) {
            invalidFields.push({name: fieldName, message: loopVal + " is not an allowed value"});
        }
    }

    //if it's an array, loop through it and call validateOne recursively
    if (_.isArray(def.type)) {
        if (!_.isArray(fieldValue)) {
            invalidFields.push({name: fieldName, message: fieldLabel + " must be an array"});
        } else if (def.min && fieldValue.length < def.min) {
            invalidFields.push({name: fieldName, message: "You must specify at least " + def.min + " values"});
        } else if (def.max && fieldValue.length > def.max) {
            invalidFields.push({name: fieldName, message: "You cannot specify more than " + def.max + " values"});
        } else {
            //if it's an array with the right number of values, etc., then we need to go through them all and
            //validate each value in the array
            var childDef = _.clone(def), loopVal;
            childDef.type = def.type[0]; //strip array off of type
            //min and max only apply to the array
            if ("min" in childDef) {
                delete childDef.min;
            }
            if ("max" in childDef) {
                delete childDef.max;
            }
            for (var i = 0, ln = fieldValue.length; i < ln; i++) {
                loopVal = fieldValue[i];
                invalidFields = _.union(invalidFields, validateOne(childDef, fieldName, fieldLabel, loopVal, isSetting));
                if (invalidFields.length) {
                    break;
                }
            }
        }
        return invalidFields;
    }
};

var dateToFieldDateString = function(date) {
    var m = (date.getUTCMonth() + 1);
    if (m < 10) {
        m = "0" + m;
    }
    var d = date.getUTCDate();
    if (d < 10) {
        d = "0" + d;
    }
    return date.getUTCFullYear() + '-' + m + '-' + d;
};

var typeconvert = function(value, type) {
    if (type === String) {
        if (typeof value !== "string") {
            return value.toString();
        }
        return value;
    }
    if (type === Number) {
        if (typeof value === "string") {
            //try to convert numeric strings to numbers
            var floatVal = parseFloat(value);
            if (!isNaN(floatVal)) {
                return floatVal;
            } else {
                return value; //leave string; will fail validation
            }
        }
        return value;
    }
    return value;
};<|endoftext|>


<commit_before>import {registerBidder} from '../src/adapters/bidderFactory.js';
import * as utils from '../src/utils.js';
import {VIDEO} from '../src/mediaTypes.js';
import {config} from '../src/config.js';

const SUPPORTED_AD_TYPES = [VIDEO];
const BIDDER_CODE = 'rise';
const BIDDER_VERSION = '4.0.1';
const TTL = 360;
const CURRENCY = 'USD';
const SELLER_ENDPOINT = 'https://hb.yellowblue.io/';
const MODES = {
  PRODUCTION: 'hb',
  TEST: 'hb-test'
}
const SUPPORTED_SYNC_METHODS = {
  IFRAME: 'iframe',
  PIXEL: 'pixel'
}

export const spec = {
  code: BIDDER_CODE,
  version: BIDDER_VERSION,
  supportedMediaTypes: SUPPORTED_AD_TYPES,
  isBidRequestValid: function(bidRequest) {
    return !!(bidRequest.params.org);
  },
  buildRequests: function (bidRequests, bidderRequest) {
    if (bidRequests.length === 0) {
      return [];
    }

    const requests = [];

    bidRequests.forEach(bid => {
      requests.push(buildVideoRequest(bid, bidderRequest));
    });

    return requests;
  },
  interpretResponse: function({body}) {
    const bidResponses = [];

    const bidResponse = {
      requestId: body.requestId,
      cpm: body.cpm,
      width: body.width,
      height: body.height,
      creativeId: body.requestId,
      currency: body.currency,
      netRevenue: body.netRevenue,
      ttl: body.ttl || TTL,
      vastXml: body.vastXml,
      mediaType: VIDEO
    };

    if (body.adomain && body.adomain.length) {
      bidResponse.meta = {};
      bidResponse.meta.advertiserDomains = body.adomain
    }
    bidResponses.push(bidResponse);

    return bidResponses;
  },
  getUserSyncs: function(syncOptions, serverResponses) {
    const syncs = [];
    for (const response of serverResponses) {
      if (syncOptions.iframeEnabled && response.body.userSyncURL) {
        syncs.push({
          type: 'iframe',
          url: response.body.userSyncURL
        });
      }
      if (syncOptions.pixelEnabled && utils.isArray(response.body.userSyncPixels)) {
        const pixels = response.body.userSyncPixels.map(pixel => {
          return {
            type: 'image',
            url: pixel
          }
        })
        syncs.push(...pixels)
      }
    }
    return syncs;
  }
};

registerBidder(spec);

/**
 * Get floor price
 * @param bid {bid}
 * @returns {Number}
 */
function getFloor(bid) {
  if (!utils.isFn(bid.getFloor)) {
    return 0;
  }
  let floorResult = bid.getFloor({
    currency: CURRENCY,
    mediaType: VIDEO,
    size: '*'
  });
  return floorResult.currency === CURRENCY ? floorResult.floor : 0;
}

/**
 * Build the video request
 * @param bid {bid}
 * @param bidderRequest {bidderRequest}
 * @returns {Object}
 */
function buildVideoRequest(bid, bidderRequest) {
  const sellerParams = generateParameters(bid, bidderRequest);
  const {params} = bid;
  return {
    method: 'GET',
    url: getEndpoint(params.testMode),
    data: sellerParams
  };
}

/**
 * Get the the ad size from the bid
 * @param bid {bid}
 * @returns {Array}
 */
function getSizes(bid) {
  if (utils.deepAccess(bid, 'mediaTypes.video.sizes')) {
    return bid.mediaTypes.video.sizes[0];
  } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) {
    return bid.sizes[0];
  }
  return [];
}

/**
 * Get schain string value
 * @param schainObject {Object}
 * @returns {string}
 */
function getSupplyChain(schainObject) {
  if (utils.isEmpty(schainObject)) {
    return '';
  }
  let scStr = `${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;
}

/**
 * Get encoded node value
 * @param val {string}
 * @returns {string}
 */
function getEncodedValIfNotEmpty(val) {
  return !utils.isEmpty(val) ? encodeURIComponent(val) : '';
}

/**
 * Get preferred user-sync method based on publisher configuration
 * @param bidderCode {string}
 * @returns {string}
 */
function getAllowedSyncMethod(filterSettings, bidderCode) {
  const iframeConfigsToCheck = ['all', 'iframe'];
  const pixelConfigToCheck = 'image';
  if (filterSettings && iframeConfigsToCheck.some(config => isSyncMethodAllowed(filterSettings[config], bidderCode))) {
    return SUPPORTED_SYNC_METHODS.IFRAME;
  }
  if (!filterSettings || !filterSettings[pixelConfigToCheck] || isSyncMethodAllowed(filterSettings[pixelConfigToCheck], bidderCode)) {
    return SUPPORTED_SYNC_METHODS.PIXEL;
  }
}

/**
 * Check if sync rule is supported
 * @param syncRule {Object}
 * @param bidderCode {string}
 * @returns {boolean}
 */
function isSyncMethodAllowed(syncRule, bidderCode) {
  if (!syncRule) {
    return false;
  }
  const isInclude = syncRule.filter === 'include';
  const bidders = utils.isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode];
  return isInclude && utils.contains(bidders, bidderCode);
}

/**
 * Get the seller endpoint
 * @param testMode {boolean}
 * @returns {string}
 */
function getEndpoint(testMode) {
  return testMode
    ? SELLER_ENDPOINT + MODES.TEST
    : SELLER_ENDPOINT + MODES.PRODUCTION;
}

/**
 * Generate query parameters for the request
 * @param bid {bid}
 * @param bidderRequest {bidderRequest}
 * @returns {Object}
 */
function generateParameters(bid, bidderRequest) {
  const timeout = config.getConfig('bidderTimeout');
  const { syncEnabled, filterSettings } = config.getConfig('userSync') || {};
  const [ width, height ] = getSizes(bid);
  const { params } = bid;
  const { bidderCode } = bidderRequest;
  const domain = window.location.hostname;

  const requestParams = {
    auction_start: utils.timestamp(),
    ad_unit_code: utils.getBidIdParameter('adUnitCode', bid),
    tmax: timeout,
    width: width,
    height: height,
    publisher_id: params.org,
    floor_price: Math.max(getFloor(bid), params.floorPrice),
    ua: navigator.userAgent,
    bid_id: utils.getBidIdParameter('bidId', bid),
    bidder_request_id: utils.getBidIdParameter('bidderRequestId', bid),
    transaction_id: utils.getBidIdParameter('transactionId', bid),
    session_id: utils.getBidIdParameter('auctionId', bid),
    publisher_name: domain,
    site_domain: domain,
    bidder_version: BIDDER_VERSION
  };

  if (params.placementId) {
    requestParams.placement_id = params.placementId;
  }

  if (syncEnabled) {
    const allowedSyncMethod = getAllowedSyncMethod(filterSettings, bidderCode);
    if (allowedSyncMethod) {
      requestParams.cs_method = allowedSyncMethod;
    }
  }

  if (bidderRequest.uspConsent) {
    requestParams.us_privacy = bidderRequest.uspConsent;
  }

  if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) {
    requestParams.gdpr = bidderRequest.gdprConsent.gdprApplies;
    requestParams.gdpr_consent = bidderRequest.gdprConsent.consentString;
  }

  if (params.ifa) {
    requestParams.ifa = params.ifa;
  }

  if (bid.schain) {
    requestParams.schain = getSupplyChain(bid.schain);
  }

  if (bidderRequest && bidderRequest.refererInfo) {
    requestParams.referrer = utils.deepAccess(bidderRequest, 'refererInfo.referer');
    requestParams.page_url = config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href');
  }

  return requestParams;
}
<commit_msg>Rise Bid Adapter: improve isBidRequestValid and size detection along with other updates (#7362)<commit_after>import {registerBidder} from '../src/adapters/bidderFactory.js';
import * as utils from '../src/utils.js';
import {VIDEO} from '../src/mediaTypes.js';
import {config} from '../src/config.js';

const SUPPORTED_AD_TYPES = [VIDEO];
const BIDDER_CODE = 'rise';
const ADAPTER_VERSION = '5.0.0';
const TTL = 360;
const CURRENCY = 'USD';
const SELLER_ENDPOINT = 'https://hb.yellowblue.io/';
const MODES = {
  PRODUCTION: 'hb',
  TEST: 'hb-test'
}
const SUPPORTED_SYNC_METHODS = {
  IFRAME: 'iframe',
  PIXEL: 'pixel'
}

export const spec = {
  code: BIDDER_CODE,
  gvlid: 1043,
  version: ADAPTER_VERSION,
  supportedMediaTypes: SUPPORTED_AD_TYPES,
  isBidRequestValid: function(bidRequest) {
    if (!bidRequest.params) {
      utils.logWarn('no params have been set to Rise adapter');
      return false;
    }

    if (!bidRequest.params.org) {
      utils.logWarn('org is a mandatory param for Rise adapter');
      return false;
    }

    return true;
  },
  buildRequests: function (bidRequests, bidderRequest) {
    if (bidRequests.length === 0) {
      return [];
    }

    const requests = [];

    bidRequests.forEach(bid => {
      requests.push(buildVideoRequest(bid, bidderRequest));
    });

    return requests;
  },
  interpretResponse: function({body}) {
    const bidResponses = [];

    const bidResponse = {
      requestId: body.requestId,
      cpm: body.cpm,
      width: body.width,
      height: body.height,
      creativeId: body.requestId,
      currency: body.currency,
      netRevenue: body.netRevenue,
      ttl: body.ttl || TTL,
      vastXml: body.vastXml,
      mediaType: VIDEO
    };

    if (body.adomain && body.adomain.length) {
      bidResponse.meta = {};
      bidResponse.meta.advertiserDomains = body.adomain
    }
    bidResponses.push(bidResponse);

    return bidResponses;
  },
  getUserSyncs: function(syncOptions, serverResponses) {
    const syncs = [];
    for (const response of serverResponses) {
      if (syncOptions.iframeEnabled && response.body.userSyncURL) {
        syncs.push({
          type: 'iframe',
          url: response.body.userSyncURL
        });
      }
      if (syncOptions.pixelEnabled && utils.isArray(response.body.userSyncPixels)) {
        const pixels = response.body.userSyncPixels.map(pixel => {
          return {
            type: 'image',
            url: pixel
          }
        })
        syncs.push(...pixels)
      }
    }
    return syncs;
  }
};

registerBidder(spec);

/**
 * Get floor price
 * @param bid {bid}
 * @returns {Number}
 */
function getFloor(bid) {
  if (!utils.isFn(bid.getFloor)) {
    return 0;
  }
  let floorResult = bid.getFloor({
    currency: CURRENCY,
    mediaType: VIDEO,
    size: '*'
  });
  return floorResult.currency === CURRENCY && floorResult.floor ? floorResult.floor : 0;
}

/**
 * Build the video request
 * @param bid {bid}
 * @param bidderRequest {bidderRequest}
 * @returns {Object}
 */
function buildVideoRequest(bid, bidderRequest) {
  const sellerParams = generateParameters(bid, bidderRequest);
  const {params} = bid;
  return {
    method: 'GET',
    url: getEndpoint(params.testMode),
    data: sellerParams
  };
}

/**
 * Get the the ad size from the bid
 * @param bid {bid}
 * @returns {Array}
 */
function getSizes(bid) {
  if (utils.deepAccess(bid, 'mediaTypes.video.sizes')) {
    return bid.mediaTypes.video.sizes[0];
  } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) {
    return bid.sizes[0];
  }
  return [];
}

/**
 * Get schain string value
 * @param schainObject {Object}
 * @returns {string}
 */
function getSupplyChain(schainObject) {
  if (utils.isEmpty(schainObject)) {
    return '';
  }
  let scStr = `${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;
}

/**
 * Get encoded node value
 * @param val {string}
 * @returns {string}
 */
function getEncodedValIfNotEmpty(val) {
  return !utils.isEmpty(val) ? encodeURIComponent(val) : '';
}

/**
 * Get preferred user-sync method based on publisher configuration
 * @param bidderCode {string}
 * @returns {string}
 */
function getAllowedSyncMethod(filterSettings, bidderCode) {
  const iframeConfigsToCheck = ['all', 'iframe'];
  const pixelConfigToCheck = 'image';
  if (filterSettings && iframeConfigsToCheck.some(config => isSyncMethodAllowed(filterSettings[config], bidderCode))) {
    return SUPPORTED_SYNC_METHODS.IFRAME;
  }
  if (!filterSettings || !filterSettings[pixelConfigToCheck] || isSyncMethodAllowed(filterSettings[pixelConfigToCheck], bidderCode)) {
    return SUPPORTED_SYNC_METHODS.PIXEL;
  }
}

/**
 * Check if sync rule is supported
 * @param syncRule {Object}
 * @param bidderCode {string}
 * @returns {boolean}
 */
function isSyncMethodAllowed(syncRule, bidderCode) {
  if (!syncRule) {
    return false;
  }
  const isInclude = syncRule.filter === 'include';
  const bidders = utils.isArray(syncRule.bidders) ? syncRule.bidders : [bidderCode];
  return isInclude && utils.contains(bidders, bidderCode);
}

/**
 * Get the seller endpoint
 * @param testMode {boolean}
 * @returns {string}
 */
function getEndpoint(testMode) {
  return testMode
    ? SELLER_ENDPOINT + MODES.TEST
    : SELLER_ENDPOINT + MODES.PRODUCTION;
}

/**
 * get device type
 * @param uad {ua}
 * @returns {string}
 */
function getDeviceType(ua) {
  if (/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i
    .test(ua.toLowerCase())) {
    return '5';
  }
  if (/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i
    .test(ua.toLowerCase())) {
    return '4';
  }
  if (/smart[-_\s]?tv|hbbtv|appletv|googletv|hdmi|netcast|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b/i
    .test(ua.toLowerCase())) {
    return '3';
  }
  return '1';
}

/**
 * Generate query parameters for the request
 * @param bid {bid}
 * @param bidderRequest {bidderRequest}
 * @returns {Object}
 */
function generateParameters(bid, bidderRequest) {
  const {params} = bid;
  const timeout = config.getConfig('bidderTimeout');
  const {syncEnabled, filterSettings} = config.getConfig('userSync') || {};
  const [width, height] = getSizes(bid);
  const {bidderCode} = bidderRequest;
  const domain = window.location.hostname;

  // fix floor price in case of NAN
  if (isNaN(params.floorPrice)) {
    params.floorPrice = 0;
  }

  const requestParams = {
    wrapper_type: 'prebidjs',
    wrapper_vendor: '$$PREBID_GLOBAL$$',
    wrapper_version: '$prebid.version$',
    adapter_version: ADAPTER_VERSION,
    auction_start: utils.timestamp(),
    ad_unit_code: utils.getBidIdParameter('adUnitCode', bid),
    tmax: timeout,
    width: width,
    height: height,
    publisher_id: params.org,
    floor_price: Math.max(getFloor(bid), params.floorPrice),
    ua: navigator.userAgent,
    bid_id: utils.getBidIdParameter('bidId', bid),
    bidder_request_id: utils.getBidIdParameter('bidderRequestId', bid),
    transaction_id: utils.getBidIdParameter('transactionId', bid),
    session_id: utils.getBidIdParameter('auctionId', bid),
    publisher_name: domain,
    site_domain: domain,
    dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0,
    device_type: getDeviceType(navigator.userAgent)
  };

  const userIdsParam = utils.getBidIdParameter('userId', bid);
  if (userIdsParam) {
    requestParams.userIds = JSON.stringify(userIdsParam);
  }

  const ortb2Metadata = config.getConfig('ortb2') || {};
  if (ortb2Metadata.site) {
    requestParams.site_metadata = JSON.stringify(ortb2Metadata.site);
  }
  if (ortb2Metadata.user) {
    requestParams.user_metadata = JSON.stringify(ortb2Metadata.user);
  }

  const playbackMethod = utils.deepAccess(bid, 'mediaTypes.video.playbackmethod');
  if (playbackMethod) {
    requestParams.playback_method = playbackMethod;
  }
  const placement = utils.deepAccess(bid, 'mediaTypes.video.placement');
  if (placement) {
    requestParams.placement = placement;
  }
  const pos = utils.deepAccess(bid, 'mediaTypes.video.pos');
  if (pos) {
    requestParams.pos = pos;
  }
  const minduration = utils.deepAccess(bid, 'mediaTypes.video.minduration');
  if (minduration) {
    requestParams.min_duration = minduration;
  }
  const maxduration = utils.deepAccess(bid, 'mediaTypes.video.maxduration');
  if (maxduration) {
    requestParams.max_duration = maxduration;
  }
  const skip = utils.deepAccess(bid, 'mediaTypes.video.skip');
  if (skip) {
    requestParams.skip = skip;
  }
  const linearity = utils.deepAccess(bid, 'mediaTypes.video.linearity');
  if (linearity) {
    requestParams.linearity = linearity;
  }

  if (params.placementId) {
    requestParams.placement_id = params.placementId;
  }

  if (syncEnabled) {
    const allowedSyncMethod = getAllowedSyncMethod(filterSettings, bidderCode);
    if (allowedSyncMethod) {
      requestParams.cs_method = allowedSyncMethod;
    }
  }

  if (bidderRequest.uspConsent) {
    requestParams.us_privacy = bidderRequest.uspConsent;
  }

  if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) {
    requestParams.gdpr = bidderRequest.gdprConsent.gdprApplies;
    requestParams.gdpr_consent = bidderRequest.gdprConsent.consentString;
  }

  if (params.ifa) {
    requestParams.ifa = params.ifa;
  }

  if (bid.schain) {
    requestParams.schain = getSupplyChain(bid.schain);
  }

  if (bidderRequest && bidderRequest.refererInfo) {
    requestParams.referrer = utils.deepAccess(bidderRequest, 'refererInfo.referer');
    requestParams.page_url = config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href');
  }

  return requestParams;
}
<|endoftext|>


<commit_before>//
// ACTIONS are identified by their id
// Optionally an action can specify:
// - ignore: true
//   The action will not change the url
// - replace: true
//   The action will replace the url (not adding a new entry in the browser history)
// - isButton: true
//   The action will be triggered by a button instead of a link
//
export default {
  URL_CHANGE: {
    id: 'URL_CHANGE',
    ignore: true
  },

  AUTHENTICATE_USER: {
    id: 'AUTHENTICATE_USER',
    ignore: true
  },

  FETCH_SEARCH_RESULTS_BY_QUERY: {
    id: 'FETCH_SEARCH_RESULTS_BY_QUERY',
    ignore: true
  },
  FETCH_SEARCH_RESULTS_BY_LOCATION: {
    id: 'FETCH_SEARCH_RESULTS_BY_LOCATION',
    ignore: true
  },
  FETCH_SEARCH_RESULTS_CATEGORY: {
    id: 'FETCH_SEARCH_RESULTS_CATEGORY',
    ignore: true
  },
  SHOW_SEARCH_RESULTS: {
    id: 'SHOW_SEARCH_RESULTS'
  },

  SHOW_MAP: {
    id: 'SHOW_MAP',
    isButton: false
  },
  MAP_ADD_PANO_OVERLAY: {
    id: 'MAP_ADD_PANO_OVERLAY',
    ignore: true
  },
  MAP_REMOVE_PANO_OVERLAY: {
    id: 'MAP_REMOVE_PANO_OVERLAY',
    ignore: true
  },
  MAP_CLICK: {
    id: 'MAP_CLICK',
    ignore: true
  },
  SET_MAP_CLICK_LOCATION: {
    id: 'SET_MAP_CLICK_LOCATION',
    ignore: true
  },
  MAP_PAN: {
    id: 'MAP_PAN',
    replace: true
  },
  MAP_ZOOM: {
    id: 'MAP_ZOOM',
    replace: true
  },
  MAP_HIGHLIGHT: {
    id: 'MAP_HIGHLIGHT',
    ignore: true
  },
  MAP_START_DRAWING: {
    id: 'MAP_START_DRAWING',
    ignore: true,
    isButton: true
  },
  MAP_CLEAR_DRAWING: {
    id: 'MAP_CLEAR_DRAWING',
    isButton: true
  },
  MAP_END_DRAWING: {
    id: 'MAP_END_DRAWING',
    isButton: true
  },

  FETCH_DETAIL: {
    id: 'FETCH_DETAIL',
    ignore: true,
    isButton: false
  },
  SHOW_DETAIL: {
    id: 'SHOW_DETAIL'
  },
  DETAIL_FULLSCREEN: {
    id: 'DETAIL_FULLSCREEN',
    replace: true
  },

  FETCH_STRAATBEELD_BY_ID: {
    id: 'FETCH_STRAATBEELD_BY_ID'
  },
  FETCH_STRAATBEELD_BY_HOTSPOT: {
    id: 'FETCH_STRAATBEELD_BY_HOTSPOT',
    ignore: true
  },
  FETCH_STRAATBEELD_BY_LOCATION: {
    id: 'FETCH_STRAATBEELD_BY_LOCATION'
  },
  SHOW_STRAATBEELD_INITIAL: {
    id: 'SHOW_STRAATBEELD_INITIAL',
    ignore: true
  },
  SHOW_STRAATBEELD_SUBSEQUENT: {
    id: 'SHOW_STRAATBEELD_SUBSEQUENT',
    replace: true
  },
  STRAATBEELD_FULLSCREEN: {
    id: 'STRAATBEELD_FULLSCREEN',
    isButton: true
  },
  HIDE_STRAATBEELD: {
    id: 'HIDE_STRAATBEELD',
    ignore: true,
    isButton: true
  },
  SET_STRAATBEELD_ORIENTATION: {
    id: 'SET_STRAATBEELD_ORIENTATION',
    replace: true
  },
  SET_STRAATBEELD_HISTORY: {
    id: 'SET_STRAATBEELD_HISTORY'
  },

  FETCH_DATA_SELECTION: {
    id: 'FETCH_DATA_SELECTION',
    ignore: true
  },
  RESET_DATA_SELECTION: {
    id: 'RESET_DATA_SELECTION',
    ignore: true
  },
  SHOW_DATA_SELECTION: {
    id: 'SHOW_DATA_SELECTION'
  },
  NAVIGATE_DATA_SELECTION: {
    id: 'NAVIGATE_DATA_SELECTION'
  },
  SET_DATA_SELECTION_VIEW: {
    id: 'SET_DATA_SELECTION_VIEW',
    isButton: true
  },

  SHOW_HOME: {
    id: 'SHOW_HOME'
  },
  SHOW_PAGE: {
    id: 'SHOW_PAGE'
  },

  APPLY_FILTERS: {
    id: 'APPLY_FILTERS',
    ignore: true
  },
  EMPTY_FILTERS: {
    id: 'EMPTY_FILTERS',
    ignore: true
  }
};
<commit_msg>Action constants indenting<commit_after>//
// ACTIONS are identified by their id
// Optionally an action can specify:
// - ignore: true
//   The action will not change the url
// - replace: true
//   The action will replace the url (not adding a new entry in the browser history)
// - isButton: true
//   The action will be triggered by a button instead of a link
//
export default {
    URL_CHANGE: {
        id: 'URL_CHANGE',
        ignore: true
    },

    AUTHENTICATE_USER: {
        id: 'AUTHENTICATE_USER',
        ignore: true
    },

    FETCH_SEARCH_RESULTS_BY_QUERY: {
        id: 'FETCH_SEARCH_RESULTS_BY_QUERY',
        ignore: true
    },
    FETCH_SEARCH_RESULTS_BY_LOCATION: {
        id: 'FETCH_SEARCH_RESULTS_BY_LOCATION',
        ignore: true
    },
    FETCH_SEARCH_RESULTS_CATEGORY: {
        id: 'FETCH_SEARCH_RESULTS_CATEGORY',
        ignore: true
    },
    SHOW_SEARCH_RESULTS: {
        id: 'SHOW_SEARCH_RESULTS'
    },

    SHOW_MAP: {
        id: 'SHOW_MAP',
        isButton: false
    },
    MAP_ADD_PANO_OVERLAY: {
        id: 'MAP_ADD_PANO_OVERLAY',
        ignore: true
    },
    MAP_REMOVE_PANO_OVERLAY: {
        id: 'MAP_REMOVE_PANO_OVERLAY',
        ignore: true
    },
    MAP_CLICK: {
        id: 'MAP_CLICK',
        ignore: true
    },
    SET_MAP_CLICK_LOCATION: {
        id: 'SET_MAP_CLICK_LOCATION',
        ignore: true
    },
    MAP_PAN: {
        id: 'MAP_PAN',
        replace: true
    },
    MAP_ZOOM: {
        id: 'MAP_ZOOM',
        replace: true
    },
    MAP_HIGHLIGHT: {
        id: 'MAP_HIGHLIGHT',
        ignore: true
    },
    MAP_START_DRAWING: {
        id: 'MAP_START_DRAWING',
        ignore: true,
        isButton: true
    },
    MAP_CLEAR_DRAWING: {
        id: 'MAP_CLEAR_DRAWING',
        isButton: true
    },
    MAP_END_DRAWING: {
        id: 'MAP_END_DRAWING',
        isButton: true
    },

    FETCH_DETAIL: {
        id: 'FETCH_DETAIL',
        ignore: true,
        isButton: false
    },
    SHOW_DETAIL: {
        id: 'SHOW_DETAIL'
    },
    DETAIL_FULLSCREEN: {
        id: 'DETAIL_FULLSCREEN',
        replace: true
    },

    FETCH_STRAATBEELD_BY_ID: {
        id: 'FETCH_STRAATBEELD_BY_ID'
    },
    FETCH_STRAATBEELD_BY_HOTSPOT: {
        id: 'FETCH_STRAATBEELD_BY_HOTSPOT',
        ignore: true
    },
    FETCH_STRAATBEELD_BY_LOCATION: {
        id: 'FETCH_STRAATBEELD_BY_LOCATION'
    },
    SHOW_STRAATBEELD_INITIAL: {
        id: 'SHOW_STRAATBEELD_INITIAL',
        ignore: true
    },
    SHOW_STRAATBEELD_SUBSEQUENT: {
        id: 'SHOW_STRAATBEELD_SUBSEQUENT',
        replace: true
    },
    STRAATBEELD_FULLSCREEN: {
        id: 'STRAATBEELD_FULLSCREEN',
        isButton: true
    },
    HIDE_STRAATBEELD: {
        id: 'HIDE_STRAATBEELD',
        ignore: true,
        isButton: true
    },
    SET_STRAATBEELD_ORIENTATION: {
        id: 'SET_STRAATBEELD_ORIENTATION',
        replace: true
    },
    SET_STRAATBEELD_HISTORY: {
        id: 'SET_STRAATBEELD_HISTORY'
    },

    FETCH_DATA_SELECTION: {
        id: 'FETCH_DATA_SELECTION',
        ignore: true
    },
    RESET_DATA_SELECTION: {
        id: 'RESET_DATA_SELECTION',
        ignore: true
    },
    SHOW_DATA_SELECTION: {
        id: 'SHOW_DATA_SELECTION'
    },
    NAVIGATE_DATA_SELECTION: {
        id: 'NAVIGATE_DATA_SELECTION'
    },
    SET_DATA_SELECTION_VIEW: {
        id: 'SET_DATA_SELECTION_VIEW',
        isButton: true
    },

    SHOW_HOME: {
        id: 'SHOW_HOME'
    },
    SHOW_PAGE: {
        id: 'SHOW_PAGE'
    },

    APPLY_FILTERS: {
        id: 'APPLY_FILTERS',
        ignore: true
    },
    EMPTY_FILTERS: {
        id: 'EMPTY_FILTERS',
        ignore: true
    }
};
<|endoftext|>


<commit_before>'use strict';

var debug = require('./.')(__filename);

debug('hey there');

someMethod();

function someMethod(){
  debug('simple and easy');
  debug('debug');
  otherMethod();
}

function otherMethod(){
  debug('with useful information');
  yetAnother();
}

function yetAnother(){
  debug('just like...');
  debug('... you had imagined');
}

<commit_msg>dev: smoke tests for the library<commit_after>'use strict';

var debug = require('./.')(__filename);

debug('hey there');

someMethod();

function someMethod(){
  debug('simple and easy');
  debug('debug');
  otherMethod();
}

function otherMethod(){
  debug('with useful information');
  yetAnother();
}

function yetAnother(){
  debug('just like...');
  debug('... you had imagined');
}
<|endoftext|>


<commit_before>import _difference from 'lodash-es/difference';
import _uniq from 'lodash-es/uniq';
import _values from 'lodash-es/values';

import {
    select as d3_select,
    selectAll as d3_selectAll
} from 'd3-selection';

import { t, textDirection } from '../../util/locale';
import { localize } from './helper';

import { coreGraph } from '../../core/graph';
import { dataIntroGraph } from '../../../data/intro_graph.json';
import { modeBrowse } from '../../modes/browse';
import { osmEntity } from '../../osm/entity';
import { services } from '../../services';
import { svgIcon } from '../../svg/icon';
import { uiCurtain } from '../curtain';

import { uiIntroWelcome } from './welcome';
import { uiIntroNavigation } from './navigation';
import { uiIntroPoint } from './point';
import { uiIntroArea } from './area';
import { uiIntroLine } from './line';
import { uiIntroBuilding } from './building';
import { uiIntroStartEditing } from './start_editing';

var chapterUi = {
    welcome: uiIntroWelcome,
    navigation: uiIntroNavigation,
    point: uiIntroPoint,
    area: uiIntroArea,
    line: uiIntroLine,
    building: uiIntroBuilding,
    startEditing: uiIntroStartEditing
};

var chapterFlow = [
    'welcome',
    'navigation',
    'point',
    'area',
    'line',
    'building',
    'startEditing'
];

export function uiIntro(context) {
    var introGraph = {},
        currChapter;

    // create entities for intro graph and localize names
    for (var id in dataIntroGraph) {
        introGraph[id] = osmEntity(localize(dataIntroGraph[id]));
    }

    function intro(selection) {
        context.enter(modeBrowse(context));

        // Save current map state
        var osm = context.connection(),
            history = context.history().toJSON(),
            hash = window.location.hash,
            center = context.map().center(),
            zoom = context.map().zoom(),
            background = context.background().baseLayerSource(),
            overlays = context.background().overlayLayerSources(),
            opacity = d3_selectAll('#map .layer-background').style('opacity'),
            loadedTiles = osm && osm.loadedTiles(),
            baseEntities = context.history().graph().base().entities,
            countryCode = services.geocoder.countryCode;

        // Block saving
        context.inIntro(true);

        // Load semi-real data used in intro
        if (osm) { osm.toggle(false).reset(); }
        context.history().reset();
        context.history().merge(_values(coreGraph().load(introGraph).entities));
        context.history().checkpoint('initial');
        context.background().bing();
        overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });

        // Mock geocoder
        services.geocoder.countryCode = function(location, callback) {
            callback(null, t('intro.graph.countrycode'));
        };

        d3_selectAll('#map .layer-background').style('opacity', 1);

        var curtain = uiCurtain();
        selection.call(curtain);

        // store that the user started the walkthrough..
        context.storage('walkthrough_started', 'yes');

        // restore previous walkthrough progress..
        var storedProgress = context.storage('walkthrough_progress') || '';
        var progress = storedProgress.split(';').filter(Boolean);

        var chapters = chapterFlow.map(function(chapter, i) {
            var s = chapterUi[chapter](context, curtain.reveal)
                .on('done', function() {
                    context.presets().init();  // clear away "recent" presets

                    buttons.filter(function(d) {
                        return d.title === s.title;
                    }).classed('finished', true);

                    if (i < chapterFlow.length - 1) {
                        var next = chapterFlow[i + 1];
                        d3_select('button.chapter-' + next)
                            .classed('next', true);
                    }

                    // store walkthrough progress..
                    progress.push(chapter);
                    context.storage('walkthrough_progress', _uniq(progress).join(';'));
                });
            return s;
        });

        chapters[chapters.length - 1].on('startEditing', function() {
            // store walkthrough progress..
            progress.push('startEditing');
            context.storage('walkthrough_progress', _uniq(progress).join(';'));

            // store if walkthrough is completed..
            var incomplete = _difference(chapterFlow, progress);
            if (!incomplete.length) {
                context.storage('walkthrough_completed', 'yes');
            }

            curtain.remove();
            navwrap.remove();
            d3_selectAll('#map .layer-background').style('opacity', opacity);
            if (osm) { osm.toggle(true).reset().loadedTiles(loadedTiles); }
            context.history().reset().merge(_values(baseEntities));
            context.background().baseLayerSource(background);
            overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
            if (history) { context.history().fromJSON(history, false); }
            context.map().centerZoom(center, zoom);
            window.location.replace(hash);
            services.geocoder.countryCode = countryCode;
            context.inIntro(false);
        });

        var navwrap = selection
            .append('div')
            .attr('class', 'intro-nav-wrap fillD');

        navwrap
            .append('svg')
            .attr('class', 'intro-nav-wrap-logo')
            .append('use')
            .attr('xlink:href', '#logo-walkthrough');

        var buttonwrap = navwrap
            .append('div')
            .attr('class', 'joined')
            .selectAll('button.chapter');

        var buttons = buttonwrap
            .data(chapters)
            .enter()
            .append('button')
            .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; })
            .on('click', enterChapter);

        buttons
            .append('span')
            .text(function(d) { return t(d.title); });

        buttons
            .append('span')
            .attr('class', 'status')
            .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'));

        enterChapter(chapters[0]);

        function enterChapter(newChapter) {
            if (currChapter) { currChapter.exit(); }
            context.enter(modeBrowse(context));

            currChapter = newChapter;
            currChapter.enter();

            buttons
                .classed('next', false)
                .classed('active', function(d) {
                    return d.title === currChapter.title;
                });
        }
    }

    return intro;
}
<commit_msg>Switch to EsriWorldImagery background layer for the tutorial..<commit_after>import _difference from 'lodash-es/difference';
import _uniq from 'lodash-es/uniq';
import _values from 'lodash-es/values';

import {
    select as d3_select,
    selectAll as d3_selectAll
} from 'd3-selection';

import { t, textDirection } from '../../util/locale';
import { localize } from './helper';

import { coreGraph } from '../../core/graph';
import { dataIntroGraph } from '../../../data/intro_graph.json';
import { modeBrowse } from '../../modes/browse';
import { osmEntity } from '../../osm/entity';
import { services } from '../../services';
import { svgIcon } from '../../svg/icon';
import { uiCurtain } from '../curtain';

import { uiIntroWelcome } from './welcome';
import { uiIntroNavigation } from './navigation';
import { uiIntroPoint } from './point';
import { uiIntroArea } from './area';
import { uiIntroLine } from './line';
import { uiIntroBuilding } from './building';
import { uiIntroStartEditing } from './start_editing';

var chapterUi = {
    welcome: uiIntroWelcome,
    navigation: uiIntroNavigation,
    point: uiIntroPoint,
    area: uiIntroArea,
    line: uiIntroLine,
    building: uiIntroBuilding,
    startEditing: uiIntroStartEditing
};

var chapterFlow = [
    'welcome',
    'navigation',
    'point',
    'area',
    'line',
    'building',
    'startEditing'
];

export function uiIntro(context) {
    var introGraph = {},
        currChapter;

    // create entities for intro graph and localize names
    for (var id in dataIntroGraph) {
        introGraph[id] = osmEntity(localize(dataIntroGraph[id]));
    }

    function intro(selection) {
        context.enter(modeBrowse(context));

        // Save current map state
        var osm = context.connection(),
            history = context.history().toJSON(),
            hash = window.location.hash,
            center = context.map().center(),
            zoom = context.map().zoom(),
            background = context.background().baseLayerSource(),
            overlays = context.background().overlayLayerSources(),
            opacity = d3_selectAll('#map .layer-background').style('opacity'),
            loadedTiles = osm && osm.loadedTiles(),
            baseEntities = context.history().graph().base().entities,
            countryCode = services.geocoder.countryCode;

        // Block saving
        context.inIntro(true);

        // Load semi-real data used in intro
        if (osm) { osm.toggle(false).reset(); }
        context.history().reset();
        context.history().merge(_values(coreGraph().load(introGraph).entities));
        context.history().checkpoint('initial');

        var esri = context.background().findSource('EsriWorldImagery');
        if (esri) {
            context.background().baseLayerSource(esri);
        } else {
            context.background().bing();
        }
        overlays.forEach(function (d) {
            context.background().toggleOverlayLayer(d);
        });

        // Mock geocoder
        services.geocoder.countryCode = function(location, callback) {
            callback(null, t('intro.graph.countrycode'));
        };

        d3_selectAll('#map .layer-background').style('opacity', 1);

        var curtain = uiCurtain();
        selection.call(curtain);

        // store that the user started the walkthrough..
        context.storage('walkthrough_started', 'yes');

        // restore previous walkthrough progress..
        var storedProgress = context.storage('walkthrough_progress') || '';
        var progress = storedProgress.split(';').filter(Boolean);

        var chapters = chapterFlow.map(function(chapter, i) {
            var s = chapterUi[chapter](context, curtain.reveal)
                .on('done', function() {
                    context.presets().init();  // clear away "recent" presets

                    buttons.filter(function(d) {
                        return d.title === s.title;
                    }).classed('finished', true);

                    if (i < chapterFlow.length - 1) {
                        var next = chapterFlow[i + 1];
                        d3_select('button.chapter-' + next)
                            .classed('next', true);
                    }

                    // store walkthrough progress..
                    progress.push(chapter);
                    context.storage('walkthrough_progress', _uniq(progress).join(';'));
                });
            return s;
        });

        chapters[chapters.length - 1].on('startEditing', function() {
            // store walkthrough progress..
            progress.push('startEditing');
            context.storage('walkthrough_progress', _uniq(progress).join(';'));

            // store if walkthrough is completed..
            var incomplete = _difference(chapterFlow, progress);
            if (!incomplete.length) {
                context.storage('walkthrough_completed', 'yes');
            }

            curtain.remove();
            navwrap.remove();
            d3_selectAll('#map .layer-background').style('opacity', opacity);
            if (osm) { osm.toggle(true).reset().loadedTiles(loadedTiles); }
            context.history().reset().merge(_values(baseEntities));
            context.background().baseLayerSource(background);
            overlays.forEach(function (d) { context.background().toggleOverlayLayer(d); });
            if (history) { context.history().fromJSON(history, false); }
            context.map().centerZoom(center, zoom);
            window.location.replace(hash);
            services.geocoder.countryCode = countryCode;
            context.inIntro(false);
        });

        var navwrap = selection
            .append('div')
            .attr('class', 'intro-nav-wrap fillD');

        navwrap
            .append('svg')
            .attr('class', 'intro-nav-wrap-logo')
            .append('use')
            .attr('xlink:href', '#logo-walkthrough');

        var buttonwrap = navwrap
            .append('div')
            .attr('class', 'joined')
            .selectAll('button.chapter');

        var buttons = buttonwrap
            .data(chapters)
            .enter()
            .append('button')
            .attr('class', function(d, i) { return 'chapter chapter-' + chapterFlow[i]; })
            .on('click', enterChapter);

        buttons
            .append('span')
            .text(function(d) { return t(d.title); });

        buttons
            .append('span')
            .attr('class', 'status')
            .call(svgIcon((textDirection === 'rtl' ? '#icon-backward' : '#icon-forward'), 'inline'));

        enterChapter(chapters[0]);

        function enterChapter(newChapter) {
            if (currChapter) { currChapter.exit(); }
            context.enter(modeBrowse(context));

            currChapter = newChapter;
            currChapter.enter();

            buttons
                .classed('next', false)
                .classed('active', function(d) {
                    return d.title === currChapter.title;
                });
        }
    }

    return intro;
}
<|endoftext|>


<commit_before>const koe = require('koe')
const path = require('path')

// define a sample config that overrides/extends some default keys
const config = {
  destination: path.join(__dirname, 'dest'),
  exclude: [
    'npm-debug.log',
    'yarn.lock'
  ]
}

// define a sample middleware
function middleware (site) {
  site.log('hey!')
  site.foo = 'bar'
}

// the main execution thread. should return a promise
async function run () {
  const site = koe(config)
  site.use(middleware)
  return site.build()
}

// execute the build process and log results
run().then(res => {
  console.log(res)
}).catch(err => {
  // optionally, log errors
})
<commit_msg>add custom hooks example<commit_after>const koe = require('koe')
const path = require('path')

// define a sample config that overrides/extends some default keys
const config = {
  destination: path.join(__dirname, 'dest'),
  exclude: [
    'npm-debug.log',
    'yarn.lock'
  ]
}

// define a sample middleware
function middleware (site) {
  site.log('hey!')
  site.foo = 'bar'
}

// you can also hook into specific parts of the build process
function preconfigHook (site) {
  site.config.destination = path.join(__dirname, 'dest2')
}

// the main execution thread. should return a promise
async function run () {
  const site = koe(config)
  site.use(middleware)

  // use the pre_config hook
  site.hook('pre_config', preconfigHook)

  return site.build()
}

// execute the build process and log results
run().then(res => {
  console.log(res)
}).catch(err => {
  // optionally, log errors
  throw new Error(err)
})
<|endoftext|>


<commit_before>(function() {
  var count, logger, mpl;
  mpl = require('./');
  count = 0;
  logger = mpl('example');
  setInterval(function() {
    logger.info("counting: " + (count += 1));
    if (count === 100) {
      return process.exit();
    }
  }, 10);
}).call(this);
<commit_msg>don't need this<commit_after><|endoftext|>


<commit_before>$(this).scrollIndicator({
    color: '#088A85', // color of the element
    height: '5px',
    debugMode: false,
    showIndicator: true, // you can hide the html element to only use the hooks
    onStartScrollDocumentHandler: function (e, debugMode) {
        if (debugMode ){
            console.info('Scroll document Started');
        }
    },
    onFinishScrollDocumentHandler: function (e, debugMode) {
        if (debugMode){
            console.info('Scroll document Finished');
        }
    },
    onCompleteAnimateScrollHandler: function (e, scrollWidth, docHeight, debugMode) {
        if (debugMode) {
            console.info('Scroll animate Complete');
        }
    }
});
<commit_msg>How to use it<commit_after>$(this).scrollIndicator({
    color: '#088A85', //color of the element
    height: '5px',
    debugMode: false,
    showIndicator: true, //you can hide the html element to only use the hooks
    onStartScrollDocumentHandler: function (e, debugMode) {
        if (debugMode ){
            console.info('Scroll document Started');
        }
    },
    onFinishScrollDocumentHandler: function (e, debugMode) {
        if (debugMode){
            console.info('Scroll document Finished');
        }
    },
    onCompleteAnimateScrollHandler: function (e, scrollWidth, docHeight, debugMode) {
        if (debugMode) {
            console.info('Scroll animate Complete');
        }
    }
});
<|endoftext|>


<commit_before>var fs = require('fs')
var editorconfigIndent = require('./')
var editorconfig = fs.readFileSync('.editorconfig', 'utf-8')

var out = editorconfigIndent(editorconfig)
console.log(out)
<commit_msg>remove example.js<commit_after><|endoftext|>


<commit_before>/*--
	扩展命令
	提供扩展命令的特性
*/

//用户未输入任何命令
exports['-'] = function(argv, prj_conf, response){
	//可考虑将这个命令链接到项目文档首页
	response.end(global.HEAD_HTML.replace('{{title}}', '木有输入命令')+
		'点击这里 查看mokjs的所有内建命令。');
};

//定义print命令
exports.print = function(argv, prj_conf, response){ //通过命令的方式调用自定义的模块
	require('./demo').printPrjConfig(argv, prj_conf, response); //调用mok模块
};
<commit_msg>Delete extendCmds.js<commit_after><|endoftext|>


<commit_before>var opts = require('optimist').argv
opts.clean = opts.clean === true

var level = require('level-test')(opts)
var search = require('./')
var sublevel = require('level-sublevel')

var pull = require('pull-stream')
var pfs  = require('pull-fs')
var pl   = require('pull-level')
var bytewise = require('bytewise')

var path = require('path')

var db = sublevel(level('level-search-example', {encoding: 'json'}))

var index = search(db, 'index')

if(opts.clean) {
  pull(
    pull.values([path.join(process.env.HOME, '.npm')]),
    pfs.star(),
    pfs.star(),
    pfs.resolve('package/package.json'),
    pfs.isFile(),
    pfs.readFile(JSON.parse),
    pull.map(function (pkg) {
      console.log(pkg.name, pkg.version)
      return {
        key: pkg.name + '!' + pkg.version,
        value: pkg, type: 'put'
      }
    }),
    pl.write(db)
  )

} else if(opts.dump) {

  pull(
    pl.read(index),
    pull.map(function (data) {
      return bytewise.decode(new Buffer(data.key, 'base64'))
    }),
    pull.drain(console.log, console.log)
  )

} else {
  var q = opts._.map(function (e) {
    if('true' === e) return true
    if('false' === e) return false
    return e
  })

  if(opts.explain)
    return console.log(index.explain(q))

  pull(
    index.search(q),
    pull.map(function (data) {
      return data.value
    }),
    pull.drain(function (d) {
      console.log(d)
//      console.log({
//        name: d.name,
//        version: d.version,
//        dependencies: d.dependencies
//      })
    }, function (err) {
      if(err) throw err
    })
  )
}

<commit_msg>tidy example<commit_after>var opts = require('optimist').argv
opts.clean = opts.clean === true

var level = require('level-test')(opts)
var search = require('./')
var sublevel = require('level-sublevel')

var pull = require('pull-stream')
var pfs  = require('pull-fs')
var pl   = require('pull-level')
var bytewise = require('bytewise')

var path = require('path')

var db = sublevel(level('level-search-example', {encoding: 'json'}))

var index = search(db, 'index')

//--clean #index all package.json's in your cache.
if(opts.clean) {
  pull(
    pull.values([path.join(process.env.HOME, '.npm')]),
    pfs.star(),
    pfs.star(),
    pfs.resolve('package/package.json'),
    pfs.isFile(),
    pfs.readFile(JSON.parse),
    pull.map(function (pkg) {
      console.log(pkg.name, pkg.version)
      return {
        key: pkg.name + '!' + pkg.version,
        value: pkg, type: 'put'
      }
    }),
    pl.write(db)
  )

} else if(opts.dump) {

  pull(
    pl.read(index),
    pull.map(function (data) {
      return bytewise.decode(new Buffer(data.key, 'base64'))
    }),
    pull.drain(console.log, console.log)
  )

} else {
  var q = opts._.map(function (e) {
    if('true' === e) return true
    if('false' === e) return false
    return e
  })

  if(opts.explain)
    return console.log(index.explain(q))

  //stream results
  index.createSearchStream(q)
    .on('data', console.log)

}

<|endoftext|>


<commit_before>/**
This example demonstrates how to purchase a label for an international shipment.
Creating domestic shipment would follow a similiar proccess but would not require
the creation of CustomsItems and CustomsDeclaration objects.
**/

// replace <YOUR_PRIVATE_KEY> with your ShippoToken key
var shippo = require('shippo')('<YOUR_PRIVATE_KEY>');

var addressFrom  = {
	"object_purpose":"PURCHASE",
	"name":"Ms Hippo",
	"company":"Shippo",
	"street1":"215 Clayton St.",
	"city":"San Francisco",
	"state":"CA",
	"zip":"94117",
	"country":"US", //iso2 country code
	"phone":"+1 555 341 9393",
	"email":"ms-hippo@goshippo.com",
}

// example address_to object dict
var addressTo = {
	"object_purpose":"PURCHASE",
	"name":"Mr Hippo",
	"company":"London Zoo",
	"street1":"Regent's Park",
	"street2":"Outer Cir",
	"city":"LONDON",
	"state":"",
	"zip":"NW1 4RY",
	"country":"GB", //iso2 country code
	"phone":"+1 555 341 9393",
	"email":"mrhippo@goshippo.com",
	"metadata" : "Hippos dont lie"
}

// parcel object dict
var parcel = {
	"length":"5",
	"width":"5",
	"height":"5",
	"distance_unit":"in",
	"weight":"2",
	"mass_unit":"lb",
}

// example CustomsItems object. This is required for int'l shipment only.
var customsItem = {
	"description":"T-Shirt",
	"quantity":2,
	"net_weight":"0.3",
	"mass_unit":"lb",
	"value_amount":"20",
	"value_currency":"USD",
	"origin_country":"US",
}

// Creating the CustomsDeclaration
// (CustomsDeclaration are NOT required for domestic shipments)
shippo.customsdeclaration.create({
	"contents_type": "MERCHANDISE",
	"contents_explanation": "T-Shirt purchase",
	"non_delivery_option": "RETURN",
	"certify": true,
	"certify_signer": "Laura Behrens Wu",
	"items": [customsItem],
})
.then(function(customsDeclaration) {
	console.log("customs Declaration : %s", JSON.stringify(customsDeclaration, null, 4));
	// Creating the shipment object. In this example, the objects are directly passed to the
	// shipment.create method, Alternatively, the Address and Parcel objects could be created
	// using address.create(..) and parcel.create(..) functions respectively.
	// adding the async:false makes this call synchronous
	return shippo.shipment.create({
		"object_purpose": "PURCHASE",
		"address_from": addressFrom,
		"address_to": addressTo,
		"parcel": parcel,
		"submission_type": "DROPOFF",
		"customs_declaration": customsDeclaration.object_id,
		"async": false
	})

}, function(err) {
	// Deal with an error
	console.log("There was an error creating customs declaration: %s", err);
})
.then(function(shipment) {
	console.log("shipment : %s", JSON.stringify(shipment, null, 4));
	shippo.shipment.rates(shipment.object_id)
	.then(function(rates) {
		console.log("rates : %s", JSON.stringify(rates, null, 4));
		// Get the first rate in the rates results for demo purposes.
		rate = rates.results[0];
		// Purchase the desired rate
		return shippo.transaction.create({"rate": rate.object_id, "async": false})
	}, function(err) {
		// Deal with an error
		console.log("There was an error retrieving rates : %s", err);
	})
	.then(function(transaction) {
			console.log("transaction : %s", JSON.stringify(transaction, null, 4));
			//Wait for transaction to be proccessed
			// print label_url and tracking_number
			if(transaction.object_status == "SUCCESS") {
				console.log("Label URL: %s", transaction.label_url);
				console.log("Tracking Number: %s", transaction.tracking_number);
			}else{
				//Deal with an error with the transaction
				console.log("Message: %s", transaction.messages);
			}

	}, function(err) {
		// Deal with an error
		console.log("There was an error creating transaction : %s", err);
	});
},function(err) {
	// Deal with an error
	console.log("There was an error creating shipment: %s", err);
});
<commit_msg>Update example.js<commit_after>/**
This example demonstrates how to purchase a label for an international shipment.
Creating domestic shipment would follow a similiar proccess but would not require
the creation of CustomsItems and CustomsDeclaration objects.
**/

// replace <YOUR_PRIVATE_KEY> with your ShippoToken key
var shippo = require('shippo')('<YOUR_PRIVATE_KEY>');

var addressFrom  = {
	"object_purpose":"PURCHASE",
	"name":"Ms Hippo",
	"company":"Shippo",
	"street1":"215 Clayton St.",
	"city":"San Francisco",
	"state":"CA",
	"zip":"94117",
	"country":"US", //iso2 country code
	"phone":"+1 555 341 9393",
	"email":"ms-hippo@goshippo.com",
}

// example address_to object dict
var addressTo = {
	"object_purpose":"PURCHASE",
	"name":"Mr Hippo",
	"company":"London Zoo",
	"street1":"Regent's Park",
	"street2":"Outer Cir",
	"city":"LONDON",
	"state":"",
	"zip":"NW1 4RY",
	"country":"GB", //iso2 country code
	"phone":"+1 555 341 9393",
	"email":"mrhippo@goshippo.com",
	"metadata" : "Hippos dont lie"
}

// parcel object dict
var parcel = {
	"length":"5",
	"width":"5",
	"height":"5",
	"distance_unit":"in",
	"weight":"2",
	"mass_unit":"lb",
}

// example CustomsItems object. This is required for int'l shipment only.
var customsItem = {
	"description":"T-Shirt",
	"quantity":2,
	"net_weight":"0.3",
	"mass_unit":"lb",
	"value_amount":"20",
	"value_currency":"USD",
	"origin_country":"US",
}

// Creating the CustomsDeclaration
// (CustomsDeclaration are NOT required for domestic shipments)
shippo.customsdeclaration.create({
	"contents_type": "MERCHANDISE",
	"contents_explanation": "T-Shirt purchase",
	"non_delivery_option": "RETURN",
	"certify": true,
	"certify_signer": "Laura Behrens Wu",
	"items": [customsItem],
})
.then(function(customsDeclaration) {
	console.log("customs Declaration : %s", JSON.stringify(customsDeclaration, null, 4));
	// Creating the shipment object. In this example, the objects are directly passed to the
	// shipment.create method, Alternatively, the Address and Parcel objects could be created
	// using address.create(..) and parcel.create(..) functions respectively.
	// adding the async:false makes this call synchronous
	return shippo.shipment.create({
		"object_purpose": "PURCHASE",
		"address_from": addressFrom,
		"address_to": addressTo,
		"parcel": parcel,
		"submission_type": "DROPOFF",
		"customs_declaration": customsDeclaration.object_id,
		"async": false
	})

}, function(err) {
	// Deal with an error
	console.log("There was an error creating customs declaration: %s", err);
})
.then(function(shipment) {
	console.log("shipment : %s", JSON.stringify(shipment, null, 4));
	shippo.shipment.rates(shipment.object_id)
	.then(function(rates) {
		console.log("rates : %s", JSON.stringify(rates, null, 4));
		// Get the first rate in the rates results for demo purposes.
		rate = rates.results[0];
		// Purchase the desired rate
		return shippo.transaction.create({"rate": rate.object_id, "async": false})
	}, function(err) {
		// Deal with an error
		console.log("There was an error retrieving rates : %s", err);
	})
	.then(function(transaction) {
			console.log("transaction : %s", JSON.stringify(transaction, null, 4));
			// print label_url and tracking_number
			if(transaction.object_status == "SUCCESS") {
				console.log("Label URL: %s", transaction.label_url);
				console.log("Tracking Number: %s", transaction.tracking_number);
			}else{
				//Deal with an error with the transaction
				console.log("Message: %s", transaction.messages);
			}

	}, function(err) {
		// Deal with an error
		console.log("There was an error creating transaction : %s", err);
	});
},function(err) {
	// Deal with an error
	console.log("There was an error creating shipment: %s", err);
});
<|endoftext|>


<commit_before>/*
 * Idempotent migration script goes here.
 * Please try to avoid using migration script and instead make special treatment in the code!
 */

// BRCD-576 (Deactivate / reactivate payment gateway)
db.subscribers.find({type: 'account', payment_gateway: {$exists: 1}, 'payment_gateway.active': {$exists: 0}}).forEach(
		function (obj) {
			var ele = {active: obj.payment_gateway};
			obj.payment_gateway = ele;
			db.subscribers.save(obj);
		}
);

// BRCD-594 (Override product price in plan / plan includes products - migration script)
//  run over rates
//  fill gropus dictionary
//  move override prices from rate to plan
var gruopD = {};
db.rates.find({'to': {$gt: new Date()}}).forEach(function (product) {
	var rates = product.rates;
	for (var type in rates) {
		for (var planKey in rates[type]) {
			if (planKey == "groups") {
				for (var gruop in rates[type][planKey]) {
					var groupName = rates[type][planKey][gruop];
					if (!gruopD.hasOwnProperty(groupName)) {
						gruopD[groupName] = [];
					}
					var alreadyExist = false;
					for (var i = 0; i < gruopD[groupName].length; i++) {
						if (gruopD[groupName][i] == product.key)
							alreadyExist = true;
					}
					if (!alreadyExist)
						gruopD[groupName].push(product.key);
				}
				delete rates[type][planKey];
			} else if (planKey != "BASE") {
				planDoc = db.plans.findOne({'name': planKey, 'to': {$gt: new Date()}});
				if (planDoc != null) {
					if (!planDoc.hasOwnProperty('rates')) {
						planDoc['rates'] = {};
					}
					if (!planDoc['rates'].hasOwnProperty(product.key)) {
						planDoc['rates'][product.key] = {};
					}
					planDoc['rates'][product.key][type] = rates[type][planKey];
				}
				db.plans.save(planDoc);
				delete rates[type][planKey];
			}
		}
	}
	product.rates = rates;
	db.rates.save(product);
});
//  run over plans
//  add rates array to each group
db.plans.find({'to': {$gt: new Date()}}).forEach(function (plan) {
	if (plan.hasOwnProperty("include")) {
		var groupsInPlan = plan.include.groups;
		for (var group in groupsInPlan) {
			if (gruopD.hasOwnProperty(group)) {
				groupsInPlan[group]["rates"] = gruopD[group];
			}
		}
		plan.include.groups = groupsInPlan;
		db.plans.save(plan);
	}
});
//  run over services
//  add rates array to each group
db.services.find({'to': {$gt: new Date()}}).forEach(function (service) {
	if (service.hasOwnProperty("include")) {
		var groupsInService = service.include.groups;
		for (var group in groupsInService) {
			if (gruopD.hasOwnProperty(group)) {
				groupsInService[group]["rates"] = gruopD[group];
			}
		}
		service.include.groups = groupsInService;
		db.services.save(service);
	}
});

// Add zip code account system field if it doesn't yet exist
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	var found_zip_code = false;
	lastConfig.subscribers.account.fields.forEach(function (field) {
		if (field.field_name == "zip_code") {
			found_zip_code = true;
			field.unique = false;
			field.generated = false;
			field.editable = true;
			field.mandatory = true;
			field.system = true;
			field.show_in_list = false;
			field.display = true;
		}
	})
	if (!found_zip_code) {
		lastConfig.subscribers.account.fields.push({
			"field_name": "zip_code",
			"title": "Zip code",
			"generated": false,
			"unique": false,
			"editable": true,
			"mandatory": true,
			"system": true,
			"show_in_list": false,
			"display": true
		});
	}

	var found_tax_field = false;
	lastConfig.rates.fields.forEach(function (field) {
		if (field.field_name == "tax") {
			found_tax_field = true;
		}
	})
	if (!found_tax_field) {
		lastConfig.rates.fields.push({
			"field_name": "tax",
		});
	}

	db.config.insert(lastConfig);
}

// BRCD-614
var serviceDic = {}
db.subscribers.find({type: "subscriber", services: {$ne: [], $exists: 1}}).forEach(function (obj) {
	var services = [];
	for (var i in obj.services) {
		var srvname = obj.services[i].name ? obj.services[i].name : obj.services[i];
		var dicKey = srvname + obj.sid;
		if (!serviceDic[dicKey]) {
			serviceDic[dicKey] = {name: srvname, from: obj.from, to: obj.to};
		} else {
			if (obj.from < serviceDic[dicKey].from) {
				serviceDic[dicKey].from = obj.from;
			}
			if (obj.to > serviceDic[dicKey].to) {
				serviceDic[dicKey].to = obj.to;
			}
		}

	}
});
db.subscribers.find({type: "subscriber", services: {$ne: [], $exists: 1}}).forEach(function (obj) {
	var services = [];
	for (var i in obj.services) {
		var srvname = obj.services[i].name ? obj.services[i].name : obj.services[i];
		var dicKey = srvname + obj.sid;
		services.push({name: srvname, from: serviceDic[dicKey].from, to: serviceDic[dicKey].to});
	}
	obj.services = services;
	db.subscribers.save(obj);
});

db.balances.dropIndex('sid_1_from_1_to_1_priority_1');
db.balances.ensureIndex({aid: 1, sid: 1, from: 1, to: 1, priority: 1}, {unique: true, background: true});

// BRCD-646
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if (!lastConfig.taxation || !lastConfig.taxation.tax_type) {
	delete lastConfig['_id'];
	var pricingVat = lastConfig.pricing.vat;
	delete lastConfig['pricing']['vat'];
	lastConfig.taxation = {};
	lastConfig.taxation.vat = pricingVat;
	lastConfig.taxation.tax_type = "vat";
	db.config.insert(lastConfig);
}

// BRCD-749
db.rebalance_queue.dropIndex("sid_1");
db.rebalance_queue.ensureIndex({"sid": 1, "billrun_key": 1}, {unique: true, "background": true})

// BRCD-731
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if (!lastConfig.registration_date) {
	var firstConfig = db.config.find().sort({_id: 1}).limit(1).pretty()[0];
	var registrationDate = firstConfig._id.getTimestamp();
	delete lastConfig['_id'];
	lastConfig.registration_date = registrationDate;
	db.config.insert(lastConfig);
}

//BRCD-776
db.lines.find({final_charge:{$exists:0},aprice:{$exists:1}}).forEach(function(line){
	if (typeof line.tax_data !== 'undefined') {
		line['final_charge']=line['aprice']+line['tax_data']['total_amount'];
	} else {
		line['final_charge']=line['aprice'];
	}
	db.lines.save(line);
});

// Set "Account ID" as the title for "aid" field
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	var found_aid = false;
	lastConfig.subscribers.account.fields.forEach(function (field) {
		if (field.field_name == "aid") {
			found_aid = true;
			field.title = "Account ID";
		}
	})
	if (!found_aid) {
		lastConfig.subscribers.account.fields.push({
					"field_name" : "aid",
					"generated" : true,
					"unique" : true,
					"editable" : false
				});
	}
	db.config.insert(lastConfig);
}

// subscribers / discounts indexes fixes
db.subscribers.dropIndex('sid_1_from_1_to_1');
db.subscribers.ensureIndex({'sid': 1 , 'from' : 1, 'aid' : 1}, { unique: true, sparse: true, background: true });
db.discounts.ensureIndex({'key':1, 'from': 1}, { unique: true, background: true });
db.discounts.ensureIndex({'from': 1, 'to': 1 }, { unique: false , sparse: true, background: true });
db.discounts.ensureIndex({'to': 1 }, { unique: false , sparse: true, background: true });

// Update shared secret structure
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
delete lastConfig['_id'];
if (typeof lastConfig.shared_secret.key != 'undefined') {
	lastConfig.shared_secret.name = 'key1';
	lastConfig.shared_secret.from = lastConfig.registration_date;
	lastConfig.shared_secret.to = new Date('2117/09/02');
	var ele = [];
	ele.push(lastConfig.shared_secret);
	lastConfig.shared_secret = ele;
	db.config.insert(lastConfig);
}

// Update realtime response fields
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
delete lastConfig['_id'];
var fileTypes = lastConfig['file_types'];
for (var i in fileTypes) {
	if (fileTypes[i].response && fileTypes[i].response.fields) {
		fileTypes[i].response.fields = [
			{
				"response_field_name": "requestType",
				"row_field_name": "request_type"
			},
			{
				"response_field_name": "sessionId",
				"row_field_name": "session_id"
			},
			{
				"response_field_name": "returnCode",
				"row_field_name": "granted_return_code"
			},
			{
				"response_field_name": "stamp",
				"row_field_name": "stamp"
			},
			{
				"response_field_name": "sid",
				"row_field_name": "sid"
			},
			{
				"response_field_name": "grantedVolume",
				"row_field_name": "usagev"
			},
			{
				"response_field_name": "pretend",
				"row_field_name": "billrun_pretend"
			}
		];
	}
}

lastConfig.file_types = fileTypes;
db.config.insert(lastConfig);

// BRCD-832 rename entity name from lines to usage
db.reports.find({"entity": "lines"}).forEach(function (obj) {
	obj.entity = "usage";
	db.reports.save(obj);
});

// BRCD-368 Importer - chenge account and subscriber fieds settings
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	// set subscriber plan_activation display false
	var plan_activation_index = lastConfig.subscribers.subscriber.fields.findIndex(function (field) {
		return field.field_name == "plan_activation" && typeof field.editable === "undefined"
	});
	if(plan_activation_index !== -1) {
		lastConfig.subscribers.subscriber.fields[plan_activation_index].editable = false;
	}

	db.config.insert(lastConfig);
}

// BRCD-878: add rates custom fields
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
delete lastConfig['_id'];

var additionalParams = db.rates.find({},{params:1});
var params = [];
for (var i = 0; i < additionalParams.length(); i++) {
	if (typeof additionalParams[i].params === 'undefined') {
		continue;
	}
	var keys = Object.keys(additionalParams[i].params);
	for (var j in keys) {
		params.push(keys[j]);
	}
}
var p = [...new Set(params)];
var fields = lastConfig['rates']['fields'];
for (var i in p) {
	fields.push({"field_name": "params." + p[i], "multiple":true, "title":p[i], "display":true, "editable":true});
}
lastConfig['rates']['fields'] = fields;
db.config.insert(lastConfig);

// Add firstname/lastname/email account system field if it doesn't yet exist - BRCD-724
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	var found_lastname = false;
	var found_firstname = false;
	var found_email = false;

	lastConfig.subscribers.account.fields.forEach(function (field) {
		if (field.field_name == "lastname") {
			found_lastname = true;
			field.unique = false;
			field.generated = false;
			field.editable = true;
			field.mandatory = true;
			field.system = true;
			field.display = true;
		}
		if (field.field_name == "firstname") {
			found_firstname = true;
			field.unique = false;
			field.generated = false;
			field.editable = true;
			field.mandatory = true;
			field.system = true;
			field.display = true;
		}
		if (field.field_name == "email") {
			found_email = true;
			field.unique = false;
			field.generated = false;
			field.editable = true;
			field.mandatory = true;
			field.system = true;
			field.display = true;
		}
	})

	if (!found_lastname) {
		lastConfig.subscribers.account.fields.push({
			"field_name": "lastname",
			"title": "Last name",
			"generated": false,
			"unique": false,
			"editable": true,
			"mandatory": true,
			"system": true,
			"display": true
		});
	}
	if (!found_firstname) {
		lastConfig.subscribers.account.fields.push({
			"field_name": "firstname",
			"title": "First name",
			"generated": false,
			"unique": false,
			"editable": true,
			"mandatory": true,
			"system": true,
			"display": true
		});
	}
	if (!found_email) {
		lastConfig.subscribers.account.fields.push({
			"field_name": "email",
			"title": "Email",
			"generated": false,
			"unique": false,
			"editable": true,
			"mandatory": true,
			"system": true,
			"display": true
		});
	}

	db.config.insert(lastConfig);
}

// BRCD-851 - add system flag to all system fields
var systemFields = ['sid', 'aid', 'firstname', 'lastname', 'plan', 'plan_activation', 'address', 'country', 'services'];
var conf = lastConfig['subscribers']['subscriber']['fields'];
for (var i in conf) {
	if (systemFields.indexOf(conf[i]['field_name']) !== -1) {
		conf[i]['system'] = true;
	}
}
lastConfig['subscribers']['subscriber']['fields'] = conf;

var systemFields = ['aid', 'firstname', 'lastname', 'email', 'country', 'address', 'zip_code', 'payment_gateway', 'personal_id','salutation'];
var conf = lastConfig['subscribers']['account']['fields'];
for (var i in conf) {
	if (systemFields.indexOf(conf[i]['field_name']) !== -1) {
		conf[i]['system'] = true;
	}
}
lastConfig['subscribers']['account']['fields'] = conf;

var systemFields = ['key', 'from', 'to', 'description', 'rates'];
var conf = lastConfig['rates']['fields'];
for (var i in conf) {
	if (systemFields.indexOf(conf[i]['field_name']) !== -1) {
		conf[i]['system'] = true;
	}
}
lastConfig['rates']['fields'] = conf;

var systemFields = ['from', 'to', 'name', 'price', 'description', 'upfront'];
var conf = lastConfig['plans']['fields'];
for (var i in conf) {
	if (systemFields.indexOf(conf[i]['field_name']) !== -1) {
		conf[i]['system'] = true;
	}
}
lastConfig['plans']['fields'] = conf;

var systemFields = ['from', 'to', 'name', 'price', 'description', 'include'];
var conf = lastConfig['services']['fields'];
for (var i in conf) {
	if (systemFields.indexOf(conf[i]['field_name']) !== -1) {
		conf[i]['system'] = true;
	}
}
lastConfig['services']['fields'] = conf;

db.config.insert(lastConfig);
<commit_msg>fix migration script<commit_after>/*
 * Idempotent migration script goes here.
 * Please try to avoid using migration script and instead make special treatment in the code!
 */

// BRCD-576 (Deactivate / reactivate payment gateway)
db.subscribers.find({type: 'account', payment_gateway: {$exists: 1}, 'payment_gateway.active': {$exists: 0}}).forEach(
		function (obj) {
			var ele = {active: obj.payment_gateway};
			obj.payment_gateway = ele;
			db.subscribers.save(obj);
		}
);

// BRCD-594 (Override product price in plan / plan includes products - migration script)
//  run over rates
//  fill gropus dictionary
//  move override prices from rate to plan
var gruopD = {};
db.rates.find({'to': {$gt: new Date()}}).forEach(function (product) {
	var rates = product.rates;
	for (var type in rates) {
		for (var planKey in rates[type]) {
			if (planKey == "groups") {
				for (var gruop in rates[type][planKey]) {
					var groupName = rates[type][planKey][gruop];
					if (!gruopD.hasOwnProperty(groupName)) {
						gruopD[groupName] = [];
					}
					var alreadyExist = false;
					for (var i = 0; i < gruopD[groupName].length; i++) {
						if (gruopD[groupName][i] == product.key)
							alreadyExist = true;
					}
					if (!alreadyExist)
						gruopD[groupName].push(product.key);
				}
				delete rates[type][planKey];
			} else if (planKey != "BASE") {
				planDoc = db.plans.findOne({'name': planKey, 'to': {$gt: new Date()}});
				if (planDoc != null) {
					if (!planDoc.hasOwnProperty('rates')) {
						planDoc['rates'] = {};
					}
					if (!planDoc['rates'].hasOwnProperty(product.key)) {
						planDoc['rates'][product.key] = {};
					}
					planDoc['rates'][product.key][type] = rates[type][planKey];
				}
				db.plans.save(planDoc);
				delete rates[type][planKey];
			}
		}
	}
	product.rates = rates;
	db.rates.save(product);
});
//  run over plans
//  add rates array to each group
db.plans.find({'to': {$gt: new Date()}}).forEach(function (plan) {
	if (plan.hasOwnProperty("include")) {
		var groupsInPlan = plan.include.groups;
		for (var group in groupsInPlan) {
			if (gruopD.hasOwnProperty(group)) {
				groupsInPlan[group]["rates"] = gruopD[group];
			}
		}
		plan.include.groups = groupsInPlan;
		db.plans.save(plan);
	}
});
//  run over services
//  add rates array to each group
db.services.find({'to': {$gt: new Date()}}).forEach(function (service) {
	if (service.hasOwnProperty("include")) {
		var groupsInService = service.include.groups;
		for (var group in groupsInService) {
			if (gruopD.hasOwnProperty(group)) {
				groupsInService[group]["rates"] = gruopD[group];
			}
		}
		service.include.groups = groupsInService;
		db.services.save(service);
	}
});

// Add zip code account system field if it doesn't yet exist
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	var found_zip_code = false;
	lastConfig.subscribers.account.fields.forEach(function (field) {
		if (field.field_name == "zip_code") {
			found_zip_code = true;
			field.unique = false;
			field.generated = false;
			field.editable = true;
			field.mandatory = true;
			field.system = true;
			field.show_in_list = false;
			field.display = true;
		}
	})
	if (!found_zip_code) {
		lastConfig.subscribers.account.fields.push({
			"field_name": "zip_code",
			"title": "Zip code",
			"generated": false,
			"unique": false,
			"editable": true,
			"mandatory": true,
			"system": true,
			"show_in_list": false,
			"display": true
		});
	}

	var found_tax_field = false;
	lastConfig.rates.fields.forEach(function (field) {
		if (field.field_name == "tax") {
			found_tax_field = true;
		}
	})
	if (!found_tax_field) {
		lastConfig.rates.fields.push({
			"field_name": "tax",
		});
	}

	db.config.insert(lastConfig);
}

// BRCD-614
var serviceDic = {}
db.subscribers.find({type: "subscriber", services: {$ne: [], $exists: 1}}).forEach(function (obj) {
	var services = [];
	for (var i in obj.services) {
		var srvname = obj.services[i].name ? obj.services[i].name : obj.services[i];
		var dicKey = srvname + obj.sid;
		if (!serviceDic[dicKey]) {
			serviceDic[dicKey] = {name: srvname, from: obj.from, to: obj.to};
		} else {
			if (obj.from < serviceDic[dicKey].from) {
				serviceDic[dicKey].from = obj.from;
			}
			if (obj.to > serviceDic[dicKey].to) {
				serviceDic[dicKey].to = obj.to;
			}
		}

	}
});
db.subscribers.find({type: "subscriber", services: {$ne: [], $exists: 1}}).forEach(function (obj) {
	var services = [];
	for (var i in obj.services) {
		var srvname = obj.services[i].name ? obj.services[i].name : obj.services[i];
		var dicKey = srvname + obj.sid;
		services.push({name: srvname, from: serviceDic[dicKey].from, to: serviceDic[dicKey].to});
	}
	obj.services = services;
	db.subscribers.save(obj);
});

db.balances.dropIndex('sid_1_from_1_to_1_priority_1');
db.balances.ensureIndex({aid: 1, sid: 1, from: 1, to: 1, priority: 1}, {unique: true, background: true});

// BRCD-646
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if (!lastConfig.taxation || !lastConfig.taxation.tax_type) {
	delete lastConfig['_id'];
	var pricingVat = lastConfig.pricing.vat;
	delete lastConfig['pricing']['vat'];
	lastConfig.taxation = {};
	lastConfig.taxation.vat = pricingVat;
	lastConfig.taxation.tax_type = "vat";
	db.config.insert(lastConfig);
}

// BRCD-749
db.rebalance_queue.dropIndex("sid_1");
db.rebalance_queue.ensureIndex({"sid": 1, "billrun_key": 1}, {unique: true, "background": true})

// BRCD-731
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if (!lastConfig.registration_date) {
	var firstConfig = db.config.find().sort({_id: 1}).limit(1).pretty()[0];
	var registrationDate = firstConfig._id.getTimestamp();
	delete lastConfig['_id'];
	lastConfig.registration_date = registrationDate;
	db.config.insert(lastConfig);
}

//BRCD-776
db.lines.find({final_charge:{$exists:0},aprice:{$exists:1}}).forEach(function(line){
	if (typeof line.tax_data !== 'undefined') {
		line['final_charge']=line['aprice']+line['tax_data']['total_amount'];
	} else {
		line['final_charge']=line['aprice'];
	}
	db.lines.save(line);
});

// Set "Account ID" as the title for "aid" field
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	var found_aid = false;
	lastConfig.subscribers.account.fields.forEach(function (field) {
		if (field.field_name == "aid") {
			found_aid = true;
			field.title = "Account ID";
		}
	})
	if (!found_aid) {
		lastConfig.subscribers.account.fields.push({
					"field_name" : "aid",
					"generated" : true,
					"unique" : true,
					"editable" : false
				});
	}
	db.config.insert(lastConfig);
}

// subscribers / discounts indexes fixes
db.subscribers.dropIndex('sid_1_from_1_to_1');
db.subscribers.ensureIndex({'sid': 1 , 'from' : 1, 'aid' : 1}, { unique: true, sparse: true, background: true });
db.discounts.ensureIndex({'key':1, 'from': 1}, { unique: true, background: true });
db.discounts.ensureIndex({'from': 1, 'to': 1 }, { unique: false , sparse: true, background: true });
db.discounts.ensureIndex({'to': 1 }, { unique: false , sparse: true, background: true });

// Update shared secret structure
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
delete lastConfig['_id'];
if (typeof lastConfig.shared_secret.key != 'undefined') {
	lastConfig.shared_secret.name = 'key1';
	lastConfig.shared_secret.from = lastConfig.registration_date;
	lastConfig.shared_secret.to = new Date('2117/09/02');
	var ele = [];
	ele.push(lastConfig.shared_secret);
	lastConfig.shared_secret = ele;
	db.config.insert(lastConfig);
}

// Update realtime response fields
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
delete lastConfig['_id'];
var fileTypes = lastConfig['file_types'];
for (var i in fileTypes) {
	if (fileTypes[i].response && fileTypes[i].response.fields) {
		fileTypes[i].response.fields = [
			{
				"response_field_name": "requestType",
				"row_field_name": "request_type"
			},
			{
				"response_field_name": "sessionId",
				"row_field_name": "session_id"
			},
			{
				"response_field_name": "returnCode",
				"row_field_name": "granted_return_code"
			},
			{
				"response_field_name": "stamp",
				"row_field_name": "stamp"
			},
			{
				"response_field_name": "sid",
				"row_field_name": "sid"
			},
			{
				"response_field_name": "grantedVolume",
				"row_field_name": "usagev"
			},
			{
				"response_field_name": "pretend",
				"row_field_name": "billrun_pretend"
			}
		];
	}
}

lastConfig.file_types = fileTypes;
db.config.insert(lastConfig);

// BRCD-832 rename entity name from lines to usage
db.reports.find({"entity": "lines"}).forEach(function (obj) {
	obj.entity = "usage";
	db.reports.save(obj);
});

// BRCD-368 Importer - chenge account and subscriber fieds settings
var lastConfig = db.config.find().sort({_id: -1}).limit(1).pretty()[0];
if ((typeof lastConfig) !== "undefined") {
	delete lastConfig['_id'];
	// set subscriber plan_activation display false
	var plan_activation_index = lastConfig.subscribers.subscriber.fields.findIndex(function (field) {
		return field.field_name == "plan_activation" && typeof field.editable === "undefined"
	});
	if(plan_activation_index !== -1) {
		lastConfig.subscribers.subscriber.fields[plan_activation_index].editable = false;
	}

	db.config.insert(lastConfig);
}
<|endoftext|>