<commit_before>'use strict';
/*eslint no-restricted-modules: [0]*/

let color = require('../config/color');
let moment = require('moment');

let BR = '
';
let SPACE = ' ';
let profileColor = '#24678d';
let trainersprites = [1, 2, 101, 102, 169, 170, 265, 266, 168];

/**
 * Profile constructor.
 *
 * @param {Boolean} isOnline
 * @param {Object|String} user - if isOnline then Object else String
 * @param {String} image
 */
function Profile(isOnline, user, image) {
	this.isOnline = isOnline || false;
	this.user = user || null;
	this.image = image;

	this.username = Tools.escapeHTML(this.isOnline ? this.user.name : this.user);
	this.url = Config.avatarurl || 'http://149.56.141.67:8000';
}

/**
 * Create an bold html tag element.
 *
 * Example:
 * createFont('Hello World!');
 * => 'Hello World!'
 *
 * @param {String} color
 * @param {String} text
 * @return {String}
 */
function bold(text) {
	return '' + text + '';
}

/**
 * Create an font html tag element.
 *
 * Example:
 * createFont('Hello World!', 'blue');
 * => 'Hello World!'
 *
 * @param {String} color
 * @param {String} text
 * @return {String}
 */
function font(color, text) {
	return '' + text + '';
}

/**
 * Create an img tag element.
 *
 * Example:
 * createImg('phil.png');
 * => ''
 *
 * @param {String} link
 * @return {String}
 */
function img(link) {
	return '';
}

/**
 * Create a font html element wrap around by a bold html element.
 * Uses to `profileColor` as a color.
 * Adds a colon at the end of the text and a SPACE at the end of the element.
 *
 * Example:
 * label('Name');
 * => 'Name: '
 *
 * @param {String} text
 * @return {String}
 */
function label(text) {
	return bold(font(profileColor, text + ':')) + SPACE;
}

function currencyName(amount) {
	let name = " buck";
	return amount === 1 ? name : name + "s";
}

Profile.prototype.avatar = function () {
	if (this.isOnline) {
		if (typeof this.image === 'string') return img(this.url + ':' + Config.port + '/avatars/' + this.image);
		return img('http://play.pokemonshowdown.com/sprites/trainers/' + this.image + '.png');
	}
	for (let name in Config.customAvatars) {
		if (this.username === name) {
			return img(this.url + ':' + Config.port + '/avatars/' + Config.customAvatars[name]);
		}
	}
	let selectedSprite = trainersprites[Math.floor(Math.random() * trainersprites.length)];
	return img('http://play.pokemonshowdown.com/sprites/trainers/' + selectedSprite + '.png');
};

Profile.prototype.buttonAvatar = function () {
	let css = 'border:none;background:none;padding:0;float:left;';
	return '<button style="' + css + '" name="parseCommand" value="/user ' + this.username + '">' + this.avatar() + "</button>";
};

Profile.prototype.group = function () {
	if (this.isOnline && this.user.group === ' ') return label('Group') + 'Regular User';
	if (this.isOnline) return label('Group') + Config.groups[this.user.group].name;
	for (let name in Users.usergroups) {
		if (toId(this.username) === name) {
			return label('Group') + Config.groups[Users.usergroups[name].charAt(0)].name;
		}
	}
	return label('Group') + 'Regular User';
};

Profile.prototype.money = function (amount) {
	return label('Money') + amount + currencyName(amount);
};

Profile.prototype.name = function () {
	return label('Name') + bold(font(color(toId(this.username)), this.username));
};

Profile.prototype.seen = function (timeAgo) {
	if (this.isOnline) return label('Last Seen') + font('#2ECC40', 'Currently Online');
	if (!timeAgo) return label('Last Seen') + 'Never';
	return label('Last Seen') + moment(timeAgo).fromNow();
};

Profile.prototype.show = function (callback) {
	let userid = toId(this.username);

	return this.buttonAvatar() +
		SPACE + this.name() + BR +
		SPACE + this.group() + BR +
		SPACE + this.money(Db('money').get(userid, 0)) + BR +
		SPACE + this.seen(Db('seen').get(userid)) +
		'
';
};

exports.commands = {
	profile: function (target, room, user) {
		if (!this.runBroadcast()) return;
		if (target.length >= 19) return this.sendReply("Usernames are required to be less than 19 characters long.");
		let targetUser = this.targetUserOrSelf(target);
		let profile;
		if (!targetUser) {
			profile = new Profile(false, target);
		} else {
			profile = new Profile(true, targetUser, targetUser.avatar);
		}
		this.sendReplyBox(profile.show());
	},
	profilehelp: ["/profile -	Shows information regarding user's name, group, money, and when they were last seen."],
};
<commit_msg>Setup: Add VIP Display to Profile<commit_after>'use strict';
/*eslint no-restricted-modules: [0]*/

let color = require('../config/color');
let moment = require('moment');

let BR = '
';
let SPACE = ' ';
let profileColor = '#24678d';
let trainersprites = [1, 2, 101, 102, 169, 170, 265, 266, 168];

/**
 * Profile constructor.
 *
 * @param {Boolean} isOnline
 * @param {Object|String} user - if isOnline then Object else String
 * @param {String} image
 */
function Profile(isOnline, user, image) {
	this.isOnline = isOnline || false;
	this.user = user || null;
	this.image = image;

	this.username = Tools.escapeHTML(this.isOnline ? this.user.name : this.user);
	this.url = Config.avatarurl || 'http://149.56.141.67:8000';
}

/**
 * Create an bold html tag element.
 *
 * Example:
 * createFont('Hello World!');
 * => 'Hello World!'
 *
 * @param {String} color
 * @param {String} text
 * @return {String}
 */
function bold(text) {
	return '' + text + '';
}

/**
 * Create an font html tag element.
 *
 * Example:
 * createFont('Hello World!', 'blue');
 * => 'Hello World!'
 *
 * @param {String} color
 * @param {String} text
 * @return {String}
 */
function font(color, text) {
	return '' + text + '';
}

/**
 * Create an img tag element.
 *
 * Example:
 * createImg('phil.png');
 * => ''
 *
 * @param {String} link
 * @return {String}
 */
function img(link) {
	return '';
}

/**
 * Create a font html element wrap around by a bold html element.
 * Uses to `profileColor` as a color.
 * Adds a colon at the end of the text and a SPACE at the end of the element.
 *
 * Example:
 * label('Name');
 * => 'Name: '
 *
 * @param {String} text
 * @return {String}
 */
function label(text) {
	return bold(font(profileColor, text + ':')) + SPACE;
}

function currencyName(amount) {
	let name = " buck";
	return amount === 1 ? name : name + "s";
}

Profile.prototype.avatar = function () {
	if (this.isOnline) {
		if (typeof this.image === 'string') return img(this.url + ':' + Config.port + '/avatars/' + this.image);
		return img('http://play.pokemonshowdown.com/sprites/trainers/' + this.image + '.png');
	}
	for (let name in Config.customAvatars) {
		if (this.username === name) {
			return img(this.url + ':' + Config.port + '/avatars/' + Config.customAvatars[name]);
		}
	}
	let selectedSprite = trainersprites[Math.floor(Math.random() * trainersprites.length)];
	return img('http://play.pokemonshowdown.com/sprites/trainers/' + selectedSprite + '.png');
};

Profile.prototype.buttonAvatar = function () {
	let css = 'border:none;background:none;padding:0;float:left;';
	return '<button style="' + css + '" name="parseCommand" value="/user ' + this.username + '">' + this.avatar() + "</button>";
};

Profile.prototype.group = function () {
	if (this.isOnline && this.user.group === ' ') return label('Group') + 'Regular User';
	if (this.isOnline) return label('Group') + Config.groups[this.user.group].name;
	for (let name in Users.usergroups) {
		if (toId(this.username) === name) {
			return label('Group') + Config.groups[Users.usergroups[name].charAt(0)].name;
		}
	}
	return label('Group') + 'Regular User';
};

Profile.prototype.money = function (amount) {
	return label('Money') + amount + currencyName(amount);
};

Profile.prototype.name = function () {
	return label('Name') + bold(font(color(toId(this.username)), this.username));
};

Profile.prototype.seen = function (timeAgo) {
	if (this.isOnline) return label('Last Seen') + font('#2ECC40', 'Currently Online');
	if (!timeAgo) return label('Last Seen') + 'Never';
	return label('Last Seen') + moment(timeAgo).fromNow();
};

Profile.prototype.vip = function (user) {
	if (isVip(user)) return font('#6390F0', '(VIP User)');
	return '';

};

Profile.prototype.show = function (callback) {
	let userid = toId(this.username);

	return this.buttonAvatar() +
		SPACE + this.name() + BR +
		SPACE + this.group() + SPACE + this.vip(userid) + BR +
		SPACE + this.money(Db('money').get(userid, 0)) + BR +
		SPACE + this.seen(Db('seen').get(userid)) +
		'
';
};

exports.commands = {
	profile: function (target, room, user) {
		if (!this.runBroadcast()) return;
		if (target.length >= 19) return this.sendReply("Usernames are required to be less than 19 characters long.");
		let targetUser = this.targetUserOrSelf(target);
		let profile;
		if (!targetUser) {
			profile = new Profile(false, target);
		} else {
			profile = new Profile(true, targetUser, targetUser.avatar);
		}
		this.sendReplyBox(profile.show());
	},
	profilehelp: ["/profile -	Shows information regarding user's name, group, money, and when they were last seen."],
};

<|endoftext|>


<commit_before>var basefuncs = {
  object:function(object,schema,indent){
    if(!schema.properties || schema.properties.length < 1)throw new Error("No properties defined");

    var requireds = schema.required || [] //make a list
    , errs = {};

    for (var prop in object) {
      if(object.hasOwnProperty(prop)){
        console.log(Array(indent+1).join(" ")+"Validating "+prop);
        if(!schema.properties[prop]) throw new Error("Encountered property not in schema: "+prop)
        try {
          Validator.validateObject(object[prop],schema.properties[prop],indent+1);
        } catch (e){
          e=e.message||e; //because Error and other things are weird
          errs[prop] = e;
        }
        var i = requireds.indexOf(prop);
        if (i != -1)
          requireds.splice(i, 1);
      }
    }

    //are there still items left?
    if(requireds.length > 0) throw new Error("Missing required fields: "+requireds.join());

    if(Object.keys(errs).length === 0){
      throw errs;
    }
  },
  string:function(object,schema){
    if(object.length > schema.maxLength) throw new Error("String too long"); //takes advantage of undefined comparisons always false
    if(object.length < schema.minLength) throw new Error("String too short");
  },
  number:function(object,schema){
    if(object > schema.maximum) throw new Error("Number too big");
    if(object < schema.minimum) throw new Error("Number too small");
  },
  enum:function(object,schema){
    //indexOf returns -1 when object not found
    if(schema.enum.indexOf(object)==-1) throw new Error("Object not in enum: "+object);
  },
  array:function(object,schema,indent){
    if(object.length > schema.maxItems) throw new Error("Too many items");
    if(object.length < schema.minItems) throw new Error("Too few items");
    var errs = {};
    object.forEach(function(v,i){
      console.log(Array(indent+1).join(" ")+"Validating index "+i);
      try {
        Validator.validateObject(object[i],schema.items,indent+1);
      } catch(e){
        e=e.message||e;
        errs[prop] = e;
      }
    });
    /*if(schema.uniqueItems && object.filter( //only works on array of primitives
      function(value, index, self) {
        return self.indexOf(value) == index;
      }
    ).length != object.length) throw new Error("Items are not unique");*/
    if(Object.keys(errs).length === 0){
      throw errs;
    }
  },
  date:function(object,schema){ //borrowed from http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript
    object = new Date(object);
    if(Object.prototype.toString.call(object) !== "[object Date]") throw new Error("Couldn't convert to a real Date object");
    if(isNaN(object.getTime())) throw new Error("Invalid date");
  }

};

var aliases = {
  integer:function(object,schema){
    basefuncs.number(object,schema);
    if(object % 1 != 0) throw new Error("Object is decimal where integer was expected");
  }
}

for (var attrname in aliases) { basefuncs[attrname] = aliases[attrname]; }

var typefuncs = basefuncs;

Validator = {};

Validator.validateObject = function(object,schema,indent){
  typefuncs[schema.type||(schema.enum?'enum':null)](object,schema,indent||0);
};

module.exports = Validator;<commit_msg>silly mistake<commit_after>var basefuncs = {
  object:function(object,schema,indent){
    if(!schema.properties || schema.properties.length < 1)throw new Error("No properties defined");

    var requireds = schema.required || [] //make a list
    , errs = {};

    for (var prop in object) {
      if(object.hasOwnProperty(prop)){
        console.log(Array(indent+1).join(" ")+"Validating "+prop);
        if(!schema.properties[prop]) throw new Error("Encountered property not in schema: "+prop)
        try {
          Validator.validateObject(object[prop],schema.properties[prop],indent+1);
        } catch (e){
          e=e.message||e; //because Error and other things are weird
          errs[prop] = e;
        }
        var i = requireds.indexOf(prop);
        if (i != -1)
          requireds.splice(i, 1);
      }
    }

    //are there still items left?
    if(requireds.length > 0) throw new Error("Missing required fields: "+requireds.join());

    if(Object.keys(errs).length !== 0){
      throw errs;
    }
  },
  string:function(object,schema){
    if(object.length > schema.maxLength) throw new Error("String too long"); //takes advantage of undefined comparisons always false
    if(object.length < schema.minLength) throw new Error("String too short");
  },
  number:function(object,schema){
    if(object > schema.maximum) throw new Error("Number too big");
    if(object < schema.minimum) throw new Error("Number too small");
  },
  enum:function(object,schema){
    //indexOf returns -1 when object not found
    if(schema.enum.indexOf(object)==-1) throw new Error("Object not in enum: "+object);
  },
  array:function(object,schema,indent){
    if(object.length > schema.maxItems) throw new Error("Too many items");
    if(object.length < schema.minItems) throw new Error("Too few items");
    var errs = {};
    object.forEach(function(v,i){
      console.log(Array(indent+1).join(" ")+"Validating index "+i);
      try {
        Validator.validateObject(object[i],schema.items,indent+1);
      } catch(e){
        e=e.message||e;
        errs[i] = e;
      }
    });
    /*if(schema.uniqueItems && object.filter( //only works on array of primitives
      function(value, index, self) {
        return self.indexOf(value) == index;
      }
    ).length != object.length) throw new Error("Items are not unique");*/
    if(Object.keys(errs).length !== 0){
      throw errs;
    }
  },
  date:function(object,schema){ //borrowed from http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript
    object = new Date(object);
    if(Object.prototype.toString.call(object) !== "[object Date]") throw new Error("Couldn't convert to a real Date object");
    if(isNaN(object.getTime())) throw new Error("Invalid date");
  }

};

var aliases = {
  integer:function(object,schema){
    basefuncs.number(object,schema);
    if(object % 1 != 0) throw new Error("Object is decimal where integer was expected");
  }
}

for (var attrname in aliases) { basefuncs[attrname] = aliases[attrname]; }

var typefuncs = basefuncs;

Validator = {};

Validator.validateObject = function(object,schema,indent){
  typefuncs[schema.type||(schema.enum?'enum':null)](object,schema,indent||0);
};

module.exports = Validator;<|endoftext|>


<commit_before>/*
* Created by: Master Float.
* Edited by: Kevinxzllz
*/

'use strict';

let fs = require('fs');
let path = require('path');
let selectors;

function writeIconCSS() {
	fs.appendFile('config/custom.css', selectors);
}

function logMoney(message) {
	if (!message) return;
	let file = path.join(__dirname, '../logs/money.txt');
	let date = "[" + new Date().toUTCString() + "] ";
	let msg = message + "\n";
	fs.appendFile(file, date + msg);
}

exports.commands = {
	seticon: function (target, room, user) {
		if (!this.can('eval')) return this.errorReply("Access denied.");

		let args = target.split(',');
		if (args.length < 3) return this.parse('/help seticon');
		let username = toId(args.shift());
		let image = 'background: rgba(244, 244, 244, 0.8) url("' + args.shift().trim() + '") right no-repeat;';
		selectors = '\n\n' + '  #' + toId(args.shift()) + '-userlist-user-' + username;
		args.forEach(function (room) {
		        selectors += ', #' + toId(room) + '-userlist-user-' + username;
		});
		selectors += ' { \n' + '    ' + image +  '\n  }';

		logMoney(user.name + " has set an icon to " + username + ".");
		this.privateModCommand("(" + user.name + " has set an icon to  " + username + ")");
		Rooms('staff').add('|raw|' + user.name + " has set an icon to " + username +  ".").update();
		writeIconCSS();
	},
	seticonhelp: ["/seticon [username], [image], [room 1], [room 2], etc. - Sets an icon to a user in chosen rooms."],
};
<commit_msg>Fix small error in spaces<commit_after>/*
* Created by: Master Float.
* Edited by: Kevinxzllz
*/

'use strict';

let fs = require('fs');
let path = require('path');
let selectors;

function writeIconCSS() {
	fs.appendFile('config/custom.css', selectors);
}

function logMoney(message) {
	if (!message) return;
	let file = path.join(__dirname, '../logs/money.txt');
	let date = "[" + new Date().toUTCString() + "] ";
	let msg = message + "\n";
	fs.appendFile(file, date + msg);
}

exports.commands = {
	seticon: function (target, room, user) {
		if (!this.can('eval')) return this.errorReply("Access denied.");

		let args = target.split(',');
		if (args.length < 3) return this.parse('/help seticon');
		let username = toId(args.shift());
		let image = 'background: rgba(244, 244, 244, 0.8) url("' + args.shift().trim() + '") right no-repeat;';
		selectors = '\n\n' + '  #' + toId(args.shift()) + '-userlist-user-' + username;
		args.forEach(function (room) {
			selectors += ', #' + toId(room) + '-userlist-user-' + username;
		});
		selectors += ' { \n' + '    ' + image +  '\n  }';

		logMoney(user.name + " has set an icon to " + username + ".");
		this.privateModCommand("(" + user.name + " has set an icon to  " + username + ")");
		Rooms('staff').add('|raw|' + user.name + " has set an icon to " + username +  ".").update();
		writeIconCSS();
	},
	seticonhelp: ["/seticon [username], [image], [room 1], [room 2], etc. - Sets an icon to a user in chosen rooms."],
};
<|endoftext|>


<commit_before>module.exports = {

        auth: {
                account: require("./auth/account-validator"),
                profile: require("./auth/profile-validator"),
                role: require("./auth/role-validator"),
                apiEndpoint: require("./auth/api-endpoint-validator")
        },
        master: {
                product: require("./master/product-validator"),
                buyer: require("./master/buyer-validator"),
                supplier: require("./master/supplier-validator"),
                uom: require("./master/uom-validator"),
                division: require("./master/division-validator"),
                unit: require("./master/unit-validator"),
                category: require("./master/category-validator"),
                currency: require("./master/currency-validator"),
                vat: require("./master/vat-validator"),
                budget: require('./master/budget-validator'),
                threadSpecification: require('./master/thread-specification-validator'),
                machine: require('./master/machine-validator'),
                usterClassification: require('./master/uster-classification-validator'),
                lotMachine: require('./master/lot-machine-validator'),
                yarnEquivalentConversion: require('./master/yarn-equivalent-conversion-validator'),
                uster: require('./master/uster-validator'),
                lampStandard: require('./master/lamp-standard-validator'),
                accountBank : require('./master/account-bank-validator'),
                instruction: require('./master/instruction-validator'),
        },
        purchasing: {
                purchaseOrder: require("./purchasing/purchase-order-validator"),
                purchaseOrderItem: require("./purchasing/purchase-order-item-validator"),
                purchaseOrderExternal: require("./purchasing/purchase-order-external-validator"),
                deliveryOrder: require("./purchasing/delivery-order-validator"),
                unitReceiptNote: require("./purchasing/unit-receipt-note-validator"),
                unitPaymentCorrectionNote: require("./purchasing/unit-payment-correction-note-validator"),
                unitPaymentCorrectionNoteItem: require("./purchasing/unit-payment-correction-note-item-validator"),
                UnitPaymentOrder: require("./purchasing/unit-payment-order-validator"),
                UnitPaymentOrderItem: require("./purchasing/unit-payment-order-item-validator"),
                purchaseRequest: require("./purchasing/purchase-request-validator"),
                purchaseRequestItem: require("./purchasing/purchase-request-item-validator")
        },
        production: {
                spinning:{
                        winding:{
                                windingQualitySampling : require("./production/spinning/winding/winding-quality-sampling-validator"),
                                windingProductionOutput : require("./production/spinning/winding/winding-production-output-validator")
                        }
                },
                finishingPrinting:{
                        productionOrder: require("./production/finishing-printing/production-order-validator"),
                        productionOrderDetail: require("./production/finishing-printing/production-order-detail-validator"),
                        salesContract: require("./production/finishing-printing/sales-contract-validator")

                },
                dailySpinningProductionReport : require("./production/spinning/daily-spinning-production-report-validator")
        }
};<commit_msg>add machine-type<commit_after>module.exports = {

        auth: {
                account: require("./auth/account-validator"),
                profile: require("./auth/profile-validator"),
                role: require("./auth/role-validator"),
                apiEndpoint: require("./auth/api-endpoint-validator")
        },
        master: {
                product: require("./master/product-validator"),
                buyer: require("./master/buyer-validator"),
                supplier: require("./master/supplier-validator"),
                uom: require("./master/uom-validator"),
                division: require("./master/division-validator"),
                unit: require("./master/unit-validator"),
                category: require("./master/category-validator"),
                currency: require("./master/currency-validator"),
                vat: require("./master/vat-validator"),
                budget: require('./master/budget-validator'),
                threadSpecification: require('./master/thread-specification-validator'),
                machine: require('./master/machine-validator'),
                usterClassification: require('./master/uster-classification-validator'),
                lotMachine: require('./master/lot-machine-validator'),
                yarnEquivalentConversion: require('./master/yarn-equivalent-conversion-validator'),
                uster: require('./master/uster-validator'),
                lampStandard: require('./master/lamp-standard-validator'),
                accountBank : require('./master/account-bank-validator'),
                instruction: require('./master/instruction-validator'),
                machineType:require('./master/machine-type-validator')
        },
        purchasing: {
                purchaseOrder: require("./purchasing/purchase-order-validator"),
                purchaseOrderItem: require("./purchasing/purchase-order-item-validator"),
                purchaseOrderExternal: require("./purchasing/purchase-order-external-validator"),
                deliveryOrder: require("./purchasing/delivery-order-validator"),
                unitReceiptNote: require("./purchasing/unit-receipt-note-validator"),
                unitPaymentCorrectionNote: require("./purchasing/unit-payment-correction-note-validator"),
                unitPaymentCorrectionNoteItem: require("./purchasing/unit-payment-correction-note-item-validator"),
                UnitPaymentOrder: require("./purchasing/unit-payment-order-validator"),
                UnitPaymentOrderItem: require("./purchasing/unit-payment-order-item-validator"),
                purchaseRequest: require("./purchasing/purchase-request-validator"),
                purchaseRequestItem: require("./purchasing/purchase-request-item-validator")
        },
        production: {
                spinning:{
                        winding:{
                                windingQualitySampling : require("./production/spinning/winding/winding-quality-sampling-validator"),
                                windingProductionOutput : require("./production/spinning/winding/winding-production-output-validator")
                        }
                },
                finishingPrinting:{
                        productionOrder: require("./production/finishing-printing/production-order-validator"),
                        productionOrderDetail: require("./production/finishing-printing/production-order-detail-validator"),
                        salesContract: require("./production/finishing-printing/sales-contract-validator")

                },
                dailySpinningProductionReport : require("./production/spinning/daily-spinning-production-report-validator")
        }
};<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {Constants} from './constants.js';

/**
 * @return {boolean} true if this version of Chrome supports PaymentHandler.
 */
function chromeSupportsPaymentHandler() {
  // Check if feature is enabled for user
  if (typeof google == 'undefined' ||
      !null) {
    return false;
  }

  // Payment handler isn't supported on mobile
  const mobilePlatform = window.navigator.userAgent.match(
      /Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i);
  if (mobilePlatform != null) {
    return false;
  }

  const chromeVersion = window.navigator.userAgent.match(/Chrome\/([0-9]+)\./i);
  return 'PaymentRequest' in window && chromeVersion != null &&
      Number(chromeVersion[1]) >= 68 &&
      window.navigator.vendor == 'Google Inc.';
}

/**
 * @return {boolean} true if this version of Chrome supports PaymentRequest.
 */
function chromeSupportsPaymentRequest() {
  // Opera uses chrome as rendering engine and sends almost the exact same
  // user agent as chrome thereby fooling us on android.
  const isOpera = window.navigator.userAgent.indexOf('OPR/') != -1;
  if (isOpera) {
    return false;
  }
  if (chromeSupportsPaymentHandler()) {
    return true;
  }

  if (typeof google != 'undefined' &&
      null) {
    return false;
  }
  const androidPlatform = window.navigator.userAgent.match(/Android/i);
  const chromeVersion = window.navigator.userAgent.match(/Chrome\/([0-9]+)\./i);
  return androidPlatform != null && 'PaymentRequest' in window &&
      // Make sure skipping PaymentRequest UI when only one PaymentMethod is
      // supported (starts on Google Chrome 59).
      window.navigator.vendor == 'Google Inc.' && chromeVersion != null &&
      Number(chromeVersion[1]) >= 59;
}

/**
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 *
 * @return {boolean} true if the merchant only supports tokenized cards.
 */
function doesMerchantSupportOnlyTokenizedCards(isReadyToPayRequest) {
  if (isReadyToPayRequest.apiVersion >= 2) {
    const allowedAuthMethods =
        extractAllowedAuthMethodsForCards_(isReadyToPayRequest);
    if (allowedAuthMethods && allowedAuthMethods.length == 1 &&
        allowedAuthMethods[0] == Constants.AuthMethod.CRYPTOGRAM_3DS) {
      return true;
    }
  }
  return isReadyToPayRequest.allowedPaymentMethods.length == 1 &&
      isReadyToPayRequest.allowedPaymentMethods[0] ==
      Constants.PaymentMethod.TOKENIZED_CARD;
}

/**
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @param {Constants.AuthMethod} apiV2AuthMethod
 *
 * @return {boolean} true if the merchant supports pan cards.
 */
function apiV2DoesMerchantSupportSpecifiedCardType(
    isReadyToPayRequest, apiV2AuthMethod) {
  if (isReadyToPayRequest.apiVersion >= 2) {
    const allowedAuthMethods =
        extractAllowedAuthMethodsForCards_(isReadyToPayRequest);
    if (allowedAuthMethods && allowedAuthMethods.includes(apiV2AuthMethod)) {
      return true;
    }
    return false;
  }
  return false;
}

/**
 * Validate if is secure context. Returns null if context is secure, otherwise
 * return error message.
 *
 * See https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
 *
 * @return {?string} null if current context is secure, otherwise return error
 * message.
 */
function validateSecureContext() {
  if (window.location.hostname.endsWith(Constants.TRUSTED_DOMAIN)) {
    // This is for local development.
    return null;
  }
  if (window.isSecureContext === undefined) {
    // Browser not support isSecureContext, figure out a way to validate this
    // for the unsupported browser.
    return null;
  }
  return window.isSecureContext ?
      null :
      'Google Pay APIs should be called in secure context!';
}

/**
 * Validate PaymentOptions.
 *
 * @param {!PaymentOptions} paymentOptions
 */
function validatePaymentOptions(paymentOptions) {
  if (paymentOptions.environment &&
      !Object.values(Constants.Environment)
           .includes(paymentOptions.environment)) {
    throw new Error(
        'Parameter environment in PaymentOptions can optionally be set to ' +
        'PRODUCTION, otherwise it defaults to TEST.');
  }
}

/**
 * Validate IsReadyToPayRequest.
 *
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @return {?string} errorMessage if the request is invalid.
 */
function validateIsReadyToPayRequest(isReadyToPayRequest) {
  if (!isReadyToPayRequest) {
    return 'isReadyToPayRequest must be set!';
  } else if (isReadyToPayRequest.apiVersion >= 2) {
    if (!('apiVersionMinor' in isReadyToPayRequest)) {
      return 'apiVersionMinor must be set!';
    }
    if (!isReadyToPayRequest.allowedPaymentMethods ||
        !Array.isArray(isReadyToPayRequest.allowedPaymentMethods) ||
        isReadyToPayRequest.allowedPaymentMethods.length == 0) {
      return 'for v2 allowedPaymentMethods must be set to an array containing a list of accepted payment methods';
    }
    for (var i = 0; i < isReadyToPayRequest.allowedPaymentMethods.length; i++) {
      let allowedPaymentMethod = isReadyToPayRequest.allowedPaymentMethods[i];
      if (allowedPaymentMethod['type'] == Constants.PaymentMethod.CARD) {
        if (!allowedPaymentMethod['parameters']) {
          return 'Field parameters must be setup in each allowedPaymentMethod';
        }
        var allowedCardNetworks =
            allowedPaymentMethod['parameters']['allowedCardNetworks'];
        if (!allowedCardNetworks || !Array.isArray(allowedCardNetworks) ||
            allowedCardNetworks.length == 0) {
          return 'allowedCardNetworks must be setup in parameters for type CARD';
        }
        var allowedAuthMethods =
            allowedPaymentMethod['parameters']['allowedAuthMethods'];
        if (!allowedAuthMethods || !Array.isArray(allowedAuthMethods) ||
            allowedAuthMethods.length == 0 ||
            !allowedAuthMethods.every(isAuthMethodValid)) {
          return 'allowedAuthMethods must be setup in parameters for type \'CARD\' ' +
              ' and must contain \'CRYPTOGRAM_3DS\' and/or \'PAN_ONLY\'';
        }
      }
    }
    return null;
  } else if (
      !isReadyToPayRequest.allowedPaymentMethods ||
      !Array.isArray(isReadyToPayRequest.allowedPaymentMethods) ||
      isReadyToPayRequest.allowedPaymentMethods.length == 0 ||
      !isReadyToPayRequest.allowedPaymentMethods.every(isPaymentMethodValid)) {
    return 'allowedPaymentMethods must be set to an array containing \'CARD\' ' +
        'and/or \'TOKENIZED_CARD\'!';
  }
  return null;
}

/**
 * Validate the payment method.
 *
 * @param {string} paymentMethod
 * @return {boolean} if the current payment method is valid.
 */
function isPaymentMethodValid(paymentMethod) {
  return Object.values(Constants.PaymentMethod).includes(paymentMethod);
}

/**
 * Validate the auth method.
 *
 * @param {string} authMethod
 * @return {boolean} if the current auth method is valid.
 */
function isAuthMethodValid(authMethod) {
  return Object.values(Constants.AuthMethod).includes(authMethod);
}

/**
 * Validate PaymentDataRequest.
 *
 * @param {!PaymentDataRequest} paymentDataRequest
 * @return {?string} errorMessage if the request is invalid.
 */
function validatePaymentDataRequest(paymentDataRequest) {
  if (!paymentDataRequest) {
    return 'paymentDataRequest must be set!';
  }
  if (paymentDataRequest.swg) {
    return validatePaymentDataRequestForSwg(paymentDataRequest.swg);
  } else if (!paymentDataRequest.transactionInfo) {
    return 'transactionInfo must be set!';
  } else if (!paymentDataRequest.transactionInfo.currencyCode) {
    return 'currencyCode in transactionInfo must be set!';
  } else if (
      !paymentDataRequest.transactionInfo.totalPriceStatus ||
      !Object.values(Constants.TotalPriceStatus)
           .includes(paymentDataRequest.transactionInfo.totalPriceStatus)) {
    return 'totalPriceStatus in transactionInfo must be set to one of' +
        ' NOT_CURRENTLY_KNOWN, ESTIMATED or FINAL!';
  } else if (
      paymentDataRequest.transactionInfo.totalPriceStatus !==
          'NOT_CURRENTLY_KNOWN' &&
      !paymentDataRequest.transactionInfo.totalPrice) {
    return 'totalPrice in transactionInfo must be set when' +
        ' totalPriceStatus is ESTIMATED or FINAL!';
  }

  // Validate payment data request for UPI payment method
  const allowedPaymentMethod = getUpiPaymentMethod(paymentDataRequest);
  if (allowedPaymentMethod) {
    if (!allowedPaymentMethod['parameters']) {
      return 'parameters must be set in allowedPaymentMethod!';
    }

    var parameters = allowedPaymentMethod['parameters'];
    if (!parameters['payeeVpa']) {
      return 'payeeVpa in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['payeeName']) {
      return 'payeeName in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['referenceUrl']) {
      return 'referenceUrl in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['mcc']) {
      return 'mcc in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['transactionReferenceId']) {
      return 'transactionReferenceId in allowedPaymentMethod parameters' +
          ' must be set!';
    }

    if (paymentDataRequest['transactionInfo']['currencyCode'] !== 'INR') {
      return 'currencyCode in transactionInfo must be set to INR!';
    } else if (
        paymentDataRequest['transactionInfo']['totalPriceStatus'] !== 'FINAL') {
      return 'totalPriceStatus in transactionInfo must be set to FINAL!';
    } else if (!paymentDataRequest['transactionInfo']['transactionNote']) {
      return 'transactionNote in transactionInfo must be set!';
    }
  }
  return null;
}

/**
 * Returns upi payment method object if it exists in allowed payment methods
 * or null if it doesn't
 *
 * @param {!IsReadyToPayRequest|!PaymentDataRequest} request
 * @return {?Object}
 */
function getUpiPaymentMethod(request) {
  if (!chromeSupportsPaymentRequest() || request.apiVersion < 2 ||
      !request.allowedPaymentMethods) {
    return null;
  }
  return getAllowedPaymentMethodForType_(request, Constants.PaymentMethod.UPI);
}

/**
 * Validate parameters for swg.
 *
 * @param {?SwgParameters} swgParameters
 * @return {?string} errorMessage if the request is invalid.
 */
function validatePaymentDataRequestForSwg(swgParameters) {
  if (!swgParameters) {
    return 'Swg parameters must be provided';
  }
  if (!swgParameters.skuId || !swgParameters.publicationId) {
    return 'Both skuId and publicationId must be provided';
  }
  return null;
}

/**
 * Returns the allowedAuthMethods for a card from the request.
 *
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @return {?Array<string>}
 * @private
 */
function extractAllowedAuthMethodsForCards_(isReadyToPayRequest) {
  if (isReadyToPayRequest.allowedPaymentMethods) {
    const allowedPaymentMethod = getAllowedPaymentMethodForType_(
        isReadyToPayRequest, Constants.PaymentMethod.CARD);
    if (allowedPaymentMethod && allowedPaymentMethod.parameters) {
      return allowedPaymentMethod.parameters['allowedAuthMethods'];
    }
  }
  return null;
}

/**
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @param {string} paymentMethodType
 * @return {?PaymentMethod} Return first payment method for the given type,
 *     return null if not found.
 * @private
 */
function getAllowedPaymentMethodForType_(
    isReadyToPayRequest, paymentMethodType) {
  for (var i = 0; i < isReadyToPayRequest.allowedPaymentMethods.length; i++) {
    const allowedPaymentMethod = isReadyToPayRequest.allowedPaymentMethods[i];
    if (allowedPaymentMethod.type == paymentMethodType) {
      return allowedPaymentMethod;
    }
  }
  return null;
}

export {
  apiV2DoesMerchantSupportSpecifiedCardType,
  chromeSupportsPaymentHandler,
  chromeSupportsPaymentRequest,
  doesMerchantSupportOnlyTokenizedCards,
  getUpiPaymentMethod,
  isPaymentMethodValid,
  validateIsReadyToPayRequest,
  validatePaymentOptions,
  validatePaymentDataRequest,
  validateSecureContext
};
<commit_msg>Copybara migration of following change(s): ---- Change 217899111 Internal change ----<commit_after>/**
 * @license
 * Copyright 2018 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {Constants} from './constants.js';

/**
 * @return {boolean} true if this version of Chrome supports PaymentHandler.
 */
function chromeSupportsPaymentHandler() {
  // Check if feature is enabled for user
  if (typeof google == 'undefined' ||
      !null) {
    return false;
  }

  // Payment handler isn't supported on mobile
  const mobilePlatform = window.navigator.userAgent.match(
      /Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i);
  if (mobilePlatform != null) {
    return false;
  }

  const chromeVersion = window.navigator.userAgent.match(/Chrome\/([0-9]+)\./i);
  return 'PaymentRequest' in window && chromeVersion != null &&
      Number(chromeVersion[1]) >= 68 &&
      window.navigator.vendor == 'Google Inc.';
}

/**
 * @return {boolean} true if this version of Chrome supports PaymentRequest.
 */
function chromeSupportsPaymentRequest() {
  // Opera uses chrome as rendering engine and sends almost the exact same
  // user agent as chrome thereby fooling us on android.
  const isOpera = window.navigator.userAgent.indexOf('OPR/') != -1;
  if (isOpera) {
    return false;
  }
  if (chromeSupportsPaymentHandler()) {
    return true;
  }

  const androidPlatform = window.navigator.userAgent.match(/Android/i);
  const chromeVersion = window.navigator.userAgent.match(/Chrome\/([0-9]+)\./i);
  return androidPlatform != null && 'PaymentRequest' in window &&
      // Make sure skipping PaymentRequest UI when only one PaymentMethod is
      // supported (starts on Google Chrome 59).
      window.navigator.vendor == 'Google Inc.' && chromeVersion != null &&
      Number(chromeVersion[1]) >= 59;
}

/**
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 *
 * @return {boolean} true if the merchant only supports tokenized cards.
 */
function doesMerchantSupportOnlyTokenizedCards(isReadyToPayRequest) {
  if (isReadyToPayRequest.apiVersion >= 2) {
    const allowedAuthMethods =
        extractAllowedAuthMethodsForCards_(isReadyToPayRequest);
    if (allowedAuthMethods && allowedAuthMethods.length == 1 &&
        allowedAuthMethods[0] == Constants.AuthMethod.CRYPTOGRAM_3DS) {
      return true;
    }
  }
  return isReadyToPayRequest.allowedPaymentMethods.length == 1 &&
      isReadyToPayRequest.allowedPaymentMethods[0] ==
      Constants.PaymentMethod.TOKENIZED_CARD;
}

/**
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @param {Constants.AuthMethod} apiV2AuthMethod
 *
 * @return {boolean} true if the merchant supports pan cards.
 */
function apiV2DoesMerchantSupportSpecifiedCardType(
    isReadyToPayRequest, apiV2AuthMethod) {
  if (isReadyToPayRequest.apiVersion >= 2) {
    const allowedAuthMethods =
        extractAllowedAuthMethodsForCards_(isReadyToPayRequest);
    if (allowedAuthMethods && allowedAuthMethods.includes(apiV2AuthMethod)) {
      return true;
    }
    return false;
  }
  return false;
}

/**
 * Validate if is secure context. Returns null if context is secure, otherwise
 * return error message.
 *
 * See https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
 *
 * @return {?string} null if current context is secure, otherwise return error
 * message.
 */
function validateSecureContext() {
  if (window.location.hostname.endsWith(Constants.TRUSTED_DOMAIN)) {
    // This is for local development.
    return null;
  }
  if (window.isSecureContext === undefined) {
    // Browser not support isSecureContext, figure out a way to validate this
    // for the unsupported browser.
    return null;
  }
  return window.isSecureContext ?
      null :
      'Google Pay APIs should be called in secure context!';
}

/**
 * Validate PaymentOptions.
 *
 * @param {!PaymentOptions} paymentOptions
 */
function validatePaymentOptions(paymentOptions) {
  if (paymentOptions.environment &&
      !Object.values(Constants.Environment)
           .includes(paymentOptions.environment)) {
    throw new Error(
        'Parameter environment in PaymentOptions can optionally be set to ' +
        'PRODUCTION, otherwise it defaults to TEST.');
  }
}

/**
 * Validate IsReadyToPayRequest.
 *
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @return {?string} errorMessage if the request is invalid.
 */
function validateIsReadyToPayRequest(isReadyToPayRequest) {
  if (!isReadyToPayRequest) {
    return 'isReadyToPayRequest must be set!';
  } else if (isReadyToPayRequest.apiVersion >= 2) {
    if (!('apiVersionMinor' in isReadyToPayRequest)) {
      return 'apiVersionMinor must be set!';
    }
    if (!isReadyToPayRequest.allowedPaymentMethods ||
        !Array.isArray(isReadyToPayRequest.allowedPaymentMethods) ||
        isReadyToPayRequest.allowedPaymentMethods.length == 0) {
      return 'for v2 allowedPaymentMethods must be set to an array containing a list of accepted payment methods';
    }
    for (var i = 0; i < isReadyToPayRequest.allowedPaymentMethods.length; i++) {
      let allowedPaymentMethod = isReadyToPayRequest.allowedPaymentMethods[i];
      if (allowedPaymentMethod['type'] == Constants.PaymentMethod.CARD) {
        if (!allowedPaymentMethod['parameters']) {
          return 'Field parameters must be setup in each allowedPaymentMethod';
        }
        var allowedCardNetworks =
            allowedPaymentMethod['parameters']['allowedCardNetworks'];
        if (!allowedCardNetworks || !Array.isArray(allowedCardNetworks) ||
            allowedCardNetworks.length == 0) {
          return 'allowedCardNetworks must be setup in parameters for type CARD';
        }
        var allowedAuthMethods =
            allowedPaymentMethod['parameters']['allowedAuthMethods'];
        if (!allowedAuthMethods || !Array.isArray(allowedAuthMethods) ||
            allowedAuthMethods.length == 0 ||
            !allowedAuthMethods.every(isAuthMethodValid)) {
          return 'allowedAuthMethods must be setup in parameters for type \'CARD\' ' +
              ' and must contain \'CRYPTOGRAM_3DS\' and/or \'PAN_ONLY\'';
        }
      }
    }
    return null;
  } else if (
      !isReadyToPayRequest.allowedPaymentMethods ||
      !Array.isArray(isReadyToPayRequest.allowedPaymentMethods) ||
      isReadyToPayRequest.allowedPaymentMethods.length == 0 ||
      !isReadyToPayRequest.allowedPaymentMethods.every(isPaymentMethodValid)) {
    return 'allowedPaymentMethods must be set to an array containing \'CARD\' ' +
        'and/or \'TOKENIZED_CARD\'!';
  }
  return null;
}

/**
 * Validate the payment method.
 *
 * @param {string} paymentMethod
 * @return {boolean} if the current payment method is valid.
 */
function isPaymentMethodValid(paymentMethod) {
  return Object.values(Constants.PaymentMethod).includes(paymentMethod);
}

/**
 * Validate the auth method.
 *
 * @param {string} authMethod
 * @return {boolean} if the current auth method is valid.
 */
function isAuthMethodValid(authMethod) {
  return Object.values(Constants.AuthMethod).includes(authMethod);
}

/**
 * Validate PaymentDataRequest.
 *
 * @param {!PaymentDataRequest} paymentDataRequest
 * @return {?string} errorMessage if the request is invalid.
 */
function validatePaymentDataRequest(paymentDataRequest) {
  if (!paymentDataRequest) {
    return 'paymentDataRequest must be set!';
  }
  if (paymentDataRequest.swg) {
    return validatePaymentDataRequestForSwg(paymentDataRequest.swg);
  } else if (!paymentDataRequest.transactionInfo) {
    return 'transactionInfo must be set!';
  } else if (!paymentDataRequest.transactionInfo.currencyCode) {
    return 'currencyCode in transactionInfo must be set!';
  } else if (
      !paymentDataRequest.transactionInfo.totalPriceStatus ||
      !Object.values(Constants.TotalPriceStatus)
           .includes(paymentDataRequest.transactionInfo.totalPriceStatus)) {
    return 'totalPriceStatus in transactionInfo must be set to one of' +
        ' NOT_CURRENTLY_KNOWN, ESTIMATED or FINAL!';
  } else if (
      paymentDataRequest.transactionInfo.totalPriceStatus !==
          'NOT_CURRENTLY_KNOWN' &&
      !paymentDataRequest.transactionInfo.totalPrice) {
    return 'totalPrice in transactionInfo must be set when' +
        ' totalPriceStatus is ESTIMATED or FINAL!';
  }

  // Validate payment data request for UPI payment method
  const allowedPaymentMethod = getUpiPaymentMethod(paymentDataRequest);
  if (allowedPaymentMethod) {
    if (!allowedPaymentMethod['parameters']) {
      return 'parameters must be set in allowedPaymentMethod!';
    }

    var parameters = allowedPaymentMethod['parameters'];
    if (!parameters['payeeVpa']) {
      return 'payeeVpa in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['payeeName']) {
      return 'payeeName in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['referenceUrl']) {
      return 'referenceUrl in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['mcc']) {
      return 'mcc in allowedPaymentMethod parameters must be set!';
    } else if (!parameters['transactionReferenceId']) {
      return 'transactionReferenceId in allowedPaymentMethod parameters' +
          ' must be set!';
    }

    if (paymentDataRequest['transactionInfo']['currencyCode'] !== 'INR') {
      return 'currencyCode in transactionInfo must be set to INR!';
    } else if (
        paymentDataRequest['transactionInfo']['totalPriceStatus'] !== 'FINAL') {
      return 'totalPriceStatus in transactionInfo must be set to FINAL!';
    } else if (!paymentDataRequest['transactionInfo']['transactionNote']) {
      return 'transactionNote in transactionInfo must be set!';
    }
  }
  return null;
}

/**
 * Returns upi payment method object if it exists in allowed payment methods
 * or null if it doesn't
 *
 * @param {!IsReadyToPayRequest|!PaymentDataRequest} request
 * @return {?Object}
 */
function getUpiPaymentMethod(request) {
  if (!chromeSupportsPaymentRequest() || request.apiVersion < 2 ||
      !request.allowedPaymentMethods) {
    return null;
  }
  return getAllowedPaymentMethodForType_(request, Constants.PaymentMethod.UPI);
}

/**
 * Validate parameters for swg.
 *
 * @param {?SwgParameters} swgParameters
 * @return {?string} errorMessage if the request is invalid.
 */
function validatePaymentDataRequestForSwg(swgParameters) {
  if (!swgParameters) {
    return 'Swg parameters must be provided';
  }
  if (!swgParameters.skuId || !swgParameters.publicationId) {
    return 'Both skuId and publicationId must be provided';
  }
  return null;
}

/**
 * Returns the allowedAuthMethods for a card from the request.
 *
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @return {?Array<string>}
 * @private
 */
function extractAllowedAuthMethodsForCards_(isReadyToPayRequest) {
  if (isReadyToPayRequest.allowedPaymentMethods) {
    const allowedPaymentMethod = getAllowedPaymentMethodForType_(
        isReadyToPayRequest, Constants.PaymentMethod.CARD);
    if (allowedPaymentMethod && allowedPaymentMethod.parameters) {
      return allowedPaymentMethod.parameters['allowedAuthMethods'];
    }
  }
  return null;
}

/**
 * @param {!IsReadyToPayRequest} isReadyToPayRequest
 * @param {string} paymentMethodType
 * @return {?PaymentMethod} Return first payment method for the given type,
 *     return null if not found.
 * @private
 */
function getAllowedPaymentMethodForType_(
    isReadyToPayRequest, paymentMethodType) {
  for (var i = 0; i < isReadyToPayRequest.allowedPaymentMethods.length; i++) {
    const allowedPaymentMethod = isReadyToPayRequest.allowedPaymentMethods[i];
    if (allowedPaymentMethod.type == paymentMethodType) {
      return allowedPaymentMethod;
    }
  }
  return null;
}

export {
  apiV2DoesMerchantSupportSpecifiedCardType,
  chromeSupportsPaymentHandler,
  chromeSupportsPaymentRequest,
  doesMerchantSupportOnlyTokenizedCards,
  getUpiPaymentMethod,
  isPaymentMethodValid,
  validateIsReadyToPayRequest,
  validatePaymentOptions,
  validatePaymentDataRequest,
  validateSecureContext
};
<|endoftext|>


<commit_before><commit_msg>chore(examples): Testing a config change (#19306)<commit_after><|endoftext|>


<commit_before>var seconds = formatAndPrint('%s секунду', '%s секунды', '%s секунд'),
  minutes = formatAndPrint('%s минуту', '%s минуты', '%s минут'),
  hours = formatAndPrint('%s час', '%s часа', '%s часов'),
  days = formatAndPrint('%s день', '%s дня', '%s дней'),
  weeks = formatAndPrint('%s неделю', '%s недели', '%s недель'),
  months = formatAndPrint('%s месяц', '%s месяца', '%s месяцев'),
  years = formatAndPrint('%s год', '%s года', '%s лет');

module.exports = function(number, index) {
  return [
    ['только что', 'через несколько секунд'],
    [seconds(number, ' назад'), seconds(number, 'через ', true)],
    ['минуту назад', 'через минуту'],
    [minutes(number, ' назад'), minutes(number, 'через ', true)],
    ['час назад', 'через час'],
    [hours(number, ' назад'), hours(number, 'через ', true)],
    ['вчера', 'завтра'],
    [days(number, ' назад'), days(number, 'через ', true)],
    ['неделю назад', 'через неделю'],
    [weeks(number, ' назад'), weeks(number, 'через ', true)],
    ['месяц назад', 'через месяц'],
    [months(number, ' назад'), months(number, 'через ', true)],
    ['год назад', 'через год'],
    [years(number, ' назад'), years(number, 'через ', true)]
  ][index];
};

function formatAndPrint(f, s, t) {
  return function(n, addition, isBefore) {
    return addStr(formatNum(f, s, t, n), addition, isBefore);
  }
}

function formatNum(f, s, t, n) {
  var n10 = n % 10,
    str = t;

  if (n10 === 1 && (n === 1 || n > 20)) {
    str = f;
  }

  if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) {
    str = s;
  }

  return str;
}

function addStr(source, addition, isBefore) {
  addition = addition || '';

  return isBefore ? (addition + source) : (source + addition);
}<commit_msg>significantly increase performance by reducing functions calls in runtime<commit_after>var seconds = formatAndPrint('%s секунду', '%s секунды', '%s секунд'),
  minutes = formatAndPrint('%s минуту', '%s минуты', '%s минут'),
  hours = formatAndPrint('%s час', '%s часа', '%s часов'),
  days = formatAndPrint('%s день', '%s дня', '%s дней'),
  weeks = formatAndPrint('%s неделю', '%s недели', '%s недель'),
  months = formatAndPrint('%s месяц', '%s месяца', '%s месяцев'),
  years = formatAndPrint('%s год', '%s года', '%s лет');

module.exports = function(number, index) {
  switch(index) {
    case 0: return ['только что', 'через несколько секунд'];
    case 1: return [seconds(number, ' назад'), seconds(number, 'через ', true)];
    case 2: return ['минуту назад', 'через минуту'];
    case 3: return [minutes(number, ' назад'), minutes(number, 'через ', true)];
    case 4: return ['час назад', 'через час'];
    case 5: return [hours(number, ' назад'), hours(number, 'через ', true)];
    case 6: return ['вчера', 'завтра'];
    case 7: return [days(number, ' назад'), days(number, 'через ', true)];
    case 8: return ['неделю назад', 'через неделю'];
    case 9: return [weeks(number, ' назад'), weeks(number, 'через ', true)];
    case 10: return ['месяц назад', 'через месяц'];
    case 11: return [months(number, ' назад'), months(number, 'через ', true)];
    case 12: return ['год назад', 'через год'];
    case 13: return [years(number, ' назад'), years(number, 'через ', true)];
    default: return ['', '']
  }
};

function formatAndPrint(f, s, t) {
  return function(n, addition, isBefore) {
    return addStr(formatNum(f, s, t, n), addition, isBefore);
  }
}

function formatNum(f, s, t, n) {
  var n10 = n % 10,
    str = t;

  if (n10 === 1 && (n === 1 || n > 20)) {
    str = f;
  }

  if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) {
    str = s;
  }

  return str;
}

function addStr(source, addition, isBefore) {
  addition = addition || '';

  return isBefore ? (addition + source) : (source + addition);
}<|endoftext|>


<commit_before>'use strict'

function main ({
  path = require('path'),
  childProcess: {spawnSync} = require('child_process'),
  process: {env} = require('process'),
  defaultExecutable = 'echo',
  envPrefix = ''
} = {}) {
  const {
    [`${envPrefix}_EXECUTABLE`]: executable = defaultExecutable,
    [`${envPrefix}_ARGV`]: spawnArguments = '[]',
    [`${envPrefix}_SKIP`]: skipSpawnTesting = 'false'
  } = env

  const wdir = path.resolve(__dirname, '..')

  test('JavaScript Code Style: StandardJS', () => {
    if (skipSpawnTesting.toLowerCase() === 'true') return

    expect(argv).toBeInstanceOf(Array)

    const {
      stdout,
      stderr,
      signal,
      error,
      status
    } = spawnSync(executable, argv, {cwd: wdir, shell: true})

    if (stdout === null) console.warn('respose.stdout is null')
    if (stderr === null) console.warn('respose.stderr is null')
    if (signal) console.warn(`respose.signal is ${JSON.stringify(signal)}`)
    if (error) throw error
    if (status) throw new Error(stderr + '\n' + stdout)
  })
}

module.exports = main
<commit_msg>Fix: argv is not defined<commit_after>'use strict'

function main ({
  path = require('path'),
  childProcess: {spawnSync} = require('child_process'),
  process: {env} = require('process'),
  defaultExecutable = 'echo',
  envPrefix = ''
} = {}) {
  const {
    [`${envPrefix}_EXECUTABLE`]: executable = defaultExecutable,
    [`${envPrefix}_ARGV`]: spawnArguments = '[]',
    [`${envPrefix}_SKIP`]: skipSpawnTesting = 'false'
  } = env

  const wdir = path.resolve(__dirname, '..')

  test('JavaScript Code Style: StandardJS', () => {
    if (skipSpawnTesting.toLowerCase() === 'true') return

    const argv = JSON.parse(spawnArguments)
    expect(argv).toBeInstanceOf(Array)

    const {
      stdout,
      stderr,
      signal,
      error,
      status
    } = spawnSync(executable, argv, {cwd: wdir, shell: true})

    if (stdout === null) console.warn('respose.stdout is null')
    if (stderr === null) console.warn('respose.stderr is null')
    if (signal) console.warn(`respose.signal is ${JSON.stringify(signal)}`)
    if (error) throw error
    if (status) throw new Error(stderr + '\n' + stdout)
  })
}

module.exports = main
<|endoftext|>


<commit_before>/*!
 * Copyright 2014 Red Hat, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

/**
 * Construct a token.
 *
 * Based on a JSON Web Token string, construct a token object. Optionally
 * if a `clientId` is provided, the token may be tested for roles with
 * `hasRole()`.
 *
 * @constructor
 *
 * @param {String} token The JSON Web Token formatted token string.
 * @param {String} clientId Optional clientId if this is an `access_token`.
 */
function Token (token, clientId) {
  this.token = token;
  this.clientId = clientId;

  if (token) {
    try {
      const parts = token.split('.');
      this.header = JSON.parse(new Buffer(parts[0], 'base64').toString());
      this.content = JSON.parse(new Buffer(parts[1], 'base64').toString());
      this.signature = new Buffer(parts[2], 'base64');
      this.signed = parts[0] + '.' + parts[1];
    } catch (err) {
      this.content = {
        expiresAt: 0
      };
    }
  }
}

/**
 * Determine if this token is expired.
 *
 * @return {boolean} `true` if it is expired, otherwise `false`.
 */
Token.prototype.isExpired = function isExpired () {
  return ((this.content.exp * 1000) < Date.now());
};

/**
 * Determine if this token has an associated role.
 *
 * This method is only functional if the token is constructed
 * with a `clientId` parameter.
 *
 * The parameter matches a role specification using the following rules:
 *
 * - If the name contains no colons, then the name is taken as the entire
 *   name of a role within the current application, as specified via
 *   `clientId`.
 * - If the name starts with the literal `realm:`, the subsequent portion
 *   is taken as the name of a _realm-level_ role.
 * - Otherwise, the name is split at the colon, with the first portion being
 *   taken as the name of an arbitrary application, and the subsequent portion
 *   as the name of a role with that app.
 *
 * @param {String} name The role name specifier.
 *
 * @return {boolean} `true` if this token has the specified role, otherwise `false`.
 */
Token.prototype.hasRole = function hasRole (name) {
  if (!this.clientId) {
    return false;
  }

  const parts = name.split(':');
  if (parts.length === 1) {
    return this.hasApplicationRole(this.clientId, parts[0]);
  }

  if (parts[0] === 'realm') {
    return this.hasRealmRole(parts[1]);
  }

  return this.hasApplicationRole(parts[0], parts[1]);
};

/**
 * Determine if this token has an associated specific application role.
 *
 * Even if `clientId` is not set, this method may be used to explicitly test
 * roles for any given application.
 *
 * @param {String} appName The identifier of the application to test.
 * @param {String} roleName The name of the role within that application to test.
 *
 * @return {boolean} `true` if this token has the specified role, otherwise `false`.
 */
Token.prototype.hasApplicationRole = function hasApplicationRole (appName, roleName) {
  var appRoles = this.content.resource_access[appName];

  if (!appRoles) {
    return false;
  }

  return (appRoles.roles.indexOf(roleName) >= 0);
};

/**
 * Determine if this token has an associated specific realm-level role.
 *
 * Even if `clientId` is not set, this method may be used to explicitly test
 * roles for the realm.
 *
 * @param {String} appName The identifier of the application to test.
 * @param {String} roleName The name of the role within that application to test.
 *
 * @return {boolean} `true` if this token has the specified role, otherwise `false`.
 */
Token.prototype.hasRealmRole = function hasRealmRole (roleName) {
  return (this.content.realm_access.roles.indexOf(roleName) >= 0);
};

module.exports = Token;
<commit_msg>Fixed wrong JWT token structure with expiration property<commit_after>/*!
 * Copyright 2014 Red Hat, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

/**
 * Construct a token.
 *
 * Based on a JSON Web Token string, construct a token object. Optionally
 * if a `clientId` is provided, the token may be tested for roles with
 * `hasRole()`.
 *
 * @constructor
 *
 * @param {String} token The JSON Web Token formatted token string.
 * @param {String} clientId Optional clientId if this is an `access_token`.
 */
function Token (token, clientId) {
  this.token = token;
  this.clientId = clientId;

  if (token) {
    try {
      const parts = token.split('.');
      this.header = JSON.parse(new Buffer(parts[0], 'base64').toString());
      this.content = JSON.parse(new Buffer(parts[1], 'base64').toString());
      this.signature = new Buffer(parts[2], 'base64');
      this.signed = parts[0] + '.' + parts[1];
    } catch (err) {
      this.content = {
        exp: 0
      };
    }
  }
}

/**
 * Determine if this token is expired.
 *
 * @return {boolean} `true` if it is expired, otherwise `false`.
 */
Token.prototype.isExpired = function isExpired () {
  return ((this.content.exp * 1000) < Date.now());
};

/**
 * Determine if this token has an associated role.
 *
 * This method is only functional if the token is constructed
 * with a `clientId` parameter.
 *
 * The parameter matches a role specification using the following rules:
 *
 * - If the name contains no colons, then the name is taken as the entire
 *   name of a role within the current application, as specified via
 *   `clientId`.
 * - If the name starts with the literal `realm:`, the subsequent portion
 *   is taken as the name of a _realm-level_ role.
 * - Otherwise, the name is split at the colon, with the first portion being
 *   taken as the name of an arbitrary application, and the subsequent portion
 *   as the name of a role with that app.
 *
 * @param {String} name The role name specifier.
 *
 * @return {boolean} `true` if this token has the specified role, otherwise `false`.
 */
Token.prototype.hasRole = function hasRole (name) {
  if (!this.clientId) {
    return false;
  }

  const parts = name.split(':');
  if (parts.length === 1) {
    return this.hasApplicationRole(this.clientId, parts[0]);
  }

  if (parts[0] === 'realm') {
    return this.hasRealmRole(parts[1]);
  }

  return this.hasApplicationRole(parts[0], parts[1]);
};

/**
 * Determine if this token has an associated specific application role.
 *
 * Even if `clientId` is not set, this method may be used to explicitly test
 * roles for any given application.
 *
 * @param {String} appName The identifier of the application to test.
 * @param {String} roleName The name of the role within that application to test.
 *
 * @return {boolean} `true` if this token has the specified role, otherwise `false`.
 */
Token.prototype.hasApplicationRole = function hasApplicationRole (appName, roleName) {
  var appRoles = this.content.resource_access[appName];

  if (!appRoles) {
    return false;
  }

  return (appRoles.roles.indexOf(roleName) >= 0);
};

/**
 * Determine if this token has an associated specific realm-level role.
 *
 * Even if `clientId` is not set, this method may be used to explicitly test
 * roles for the realm.
 *
 * @param {String} appName The identifier of the application to test.
 * @param {String} roleName The name of the role within that application to test.
 *
 * @return {boolean} `true` if this token has the specified role, otherwise `false`.
 */
Token.prototype.hasRealmRole = function hasRealmRole (roleName) {
  return (this.content.realm_access.roles.indexOf(roleName) >= 0);
};

module.exports = Token;
<|endoftext|>


<commit_before>import React from 'react';
import { interpolate } from 'd3-interpolate';
import * as Easing from 'd3-ease';

class Motion extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.move = this.move.bind(this);
        this.state = {items: []};
    }
    componentWillReceiveProps() {
        if (!this.moveId)
            this.moveId = requestAnimationFrame(this.move);
    }
    componentDidMount() {
        this.moveId = requestAnimationFrame(this.move)
    }
    componentWillUnmount() {
        cancelAnimationFrame(this.moveId);
    }
    move() {
        this.setState(({items: prevItems}) => {
            var {data, enter, leave, update, getKey, duration, easing, onRest} = this.props;
            var tick = performance.now();
            var dataByKey = data.reduce((acc, item) => ({...acc, [getKey(item)]: item}), {});
            var itemsByKey = prevItems.reduce((acc, item) => ({...acc, [item.key]: item}), {});
            var items = prevItems
                .map(item => {
                    var nextItem = {key: item.key, data: item.data, tick};
                    nextItem.end = !dataByKey[item.key] ? leave(item.data) : update(dataByKey[item.key]);
                    var unchanged = this.areEqual(item.end, nextItem.end);
                    var reverse = !unchanged && this.areEqual(item.start, nextItem.end);
                    if (unchanged) {
                        nextItem.rest = item.progress === 1;
                        nextItem.start = item.start;
                        var progressDelta = (nextItem.tick - item.tick) / duration(item.data);
                        nextItem.progress = Math.min(item.progress + progressDelta, 1);
                        nextItem.interpolators = item.interpolators;
                    } else {
                        nextItem.rest = false;
                        nextItem.start = reverse ? item.end : item.style;
                        nextItem.progress = reverse ? 1 - item.progress : 0;
                        nextItem.interpolators = this.getInterpolators(nextItem);
                    }
                    nextItem.style = this.interpolateStyle(nextItem, easing(item.data));
                    if (onRest && nextItem.rest && !item.rest) {
                        onRest(item.data);
                    }
                    return nextItem;
                })
                .filter(item => !item.rest || dataByKey[item.key])
                .concat(data
                    .filter(item => !itemsByKey[getKey(item)])
                    .map(item => {
                        var newItem = {key: getKey(item), data: item, progress: 0, tick, rest: false};
                        newItem.start = newItem.style = enter(item);
                        newItem.end = update(item);
                        newItem.interpolators = this.getInterpolators(newItem);
                        return newItem;
                    })
                );
            this.moveId = null;
            if (items.filter(({rest}) => !rest).length !== 0)
                this.moveId = requestAnimationFrame(this.move);
            return {items};
        })
    }
    areEqual(from, to) {
        if (Object.keys(from).length !== Object.keys(to).length)
            return false;
        for(var key in from) {
            if (from[key] !== to[key])
                return false;
        }
        return true;
    }
    getInterpolators({start, end}) {
        var interpolators = {};
        for(var key in start)
            interpolators[key] = interpolate(start[key], end[key]);
        return interpolators;
    }
    interpolateStyle({interpolators, end, progress}, easing) {
        var style = {};
        for(var key in end)
            style[key] = interpolators[key](Easing[easing](progress))
        return style;
    }
    render() {
        return this.props.children(this.state.items);
    }
}

export default Motion;
<commit_msg>Moved variable into closer to where it's used<commit_after>import React from 'react';
import { interpolate } from 'd3-interpolate';
import * as Easing from 'd3-ease';

class Motion extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.move = this.move.bind(this);
        this.state = {items: []};
    }
    componentWillReceiveProps() {
        if (!this.moveId)
            this.moveId = requestAnimationFrame(this.move);
    }
    componentDidMount() {
        this.moveId = requestAnimationFrame(this.move)
    }
    componentWillUnmount() {
        cancelAnimationFrame(this.moveId);
    }
    move() {
        this.setState(({items: prevItems}) => {
            var {data, enter, leave, update, getKey, duration, easing, onRest} = this.props;
            var tick = performance.now();
            var dataByKey = data.reduce((acc, item) => ({...acc, [getKey(item)]: item}), {});
            var itemsByKey = prevItems.reduce((acc, item) => ({...acc, [item.key]: item}), {});
            var items = prevItems
                .map(item => {
                    var nextItem = {key: item.key, data: item.data, tick};
                    nextItem.end = !dataByKey[item.key] ? leave(item.data) : update(dataByKey[item.key]);
                    var unchanged = this.areEqual(item.end, nextItem.end);
                    if (unchanged) {
                        nextItem.rest = item.progress === 1;
                        nextItem.start = item.start;
                        var progressDelta = (nextItem.tick - item.tick) / duration(item.data);
                        nextItem.progress = Math.min(item.progress + progressDelta, 1);
                        nextItem.interpolators = item.interpolators;
                    } else {
                        nextItem.rest = false;
                        var reverse = !unchanged && this.areEqual(item.start, nextItem.end);
                        nextItem.start = reverse ? item.end : item.style;
                        nextItem.progress = reverse ? 1 - item.progress : 0;
                        nextItem.interpolators = this.getInterpolators(nextItem);
                    }
                    nextItem.style = this.interpolateStyle(nextItem, easing(item.data));
                    if (onRest && nextItem.rest && !item.rest) {
                        onRest(item.data);
                    }
                    return nextItem;
                })
                .filter(item => !item.rest || dataByKey[item.key])
                .concat(data
                    .filter(item => !itemsByKey[getKey(item)])
                    .map(item => {
                        var newItem = {key: getKey(item), data: item, progress: 0, tick, rest: false};
                        newItem.start = newItem.style = enter(item);
                        newItem.end = update(item);
                        newItem.interpolators = this.getInterpolators(newItem);
                        return newItem;
                    })
                );
            this.moveId = null;
            if (items.filter(({rest}) => !rest).length !== 0)
                this.moveId = requestAnimationFrame(this.move);
            return {items};
        })
    }
    areEqual(from, to) {
        if (Object.keys(from).length !== Object.keys(to).length)
            return false;
        for(var key in from) {
            if (from[key] !== to[key])
                return false;
        }
        return true;
    }
    getInterpolators({start, end}) {
        var interpolators = {};
        for(var key in start)
            interpolators[key] = interpolate(start[key], end[key]);
        return interpolators;
    }
    interpolateStyle({interpolators, end, progress}, easing) {
        var style = {};
        for(var key in end)
            style[key] = interpolators[key](Easing[easing](progress))
        return style;
    }
    render() {
        return this.props.children(this.state.items);
    }
}

export default Motion;
<|endoftext|>


<commit_before>console.log('hello zjj');<commit_msg>test delete push<commit_after><|endoftext|>


<commit_before>const Constants  = require("./constants.js");
const Commons    = require("./commons.js");
const Cloudevent = require("../../cloudevent.js");
const Spec02     = require("../../specs/spec_0_2.js");

var JSONParser = require("../../formats/json/parser.js");

const spec02 = new Spec02();
const jsonParserSpec02 = new JSONParser();

const parser_by_mime = {};
parser_by_mime[Constants.MIME_JSON]    = jsonParserSpec02;
parser_by_mime[Constants.MIME_CE_JSON] = jsonParserSpec02;

const allowed_content_types = [];
allowed_content_types.push(Constants.MIME_CE_JSON);

function validate_args(payload, attributes) {
  if(!payload){
    throw {message: "payload is null or undefined"};
  }

  if(!attributes) {
    throw {message: "attributes is null or undefined"};
  }

  if((typeof payload) !== "object" && (typeof payload) !== "string"){
    throw {message: "payload must be an object or string",
             erros: [typeof payload]};
  }
}

function Receiver(configuration) {

}

Receiver.prototype.check = function(payload, headers) {
  validate_args(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  // Validation Level 1
  if(!allowed_content_types
      .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){
        throw {message: "invalid content type",
              errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]};
  }

  // No erros! Its contains the minimum required attributes
}

Receiver.prototype.parse = function(payload, headers) {
  this.check(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE];

  var parser = parser_by_mime[contentType];

  var cloudevent = parser.parse(payload);

  // Must follow the spec
  spec02.check(cloudevent);

  return cloudevent;
}

module.exports = Receiver;
<commit_msg>Extension processing and cloudevent right parse<commit_after>const Constants  = require("./constants.js");
const Commons    = require("./commons.js");
const Cloudevent = require("../../cloudevent.js");
const Spec02     = require("../../specs/spec_0_2.js");

var JSONParser = require("../../formats/json/parser.js");

const spec02 = new Spec02();
const jsonParserSpec02 = new JSONParser();

const parser_by_mime = {};
parser_by_mime[Constants.MIME_JSON]    = jsonParserSpec02;
parser_by_mime[Constants.MIME_CE_JSON] = jsonParserSpec02;

const allowed_content_types = [];
allowed_content_types.push(Constants.MIME_CE_JSON);

const setter_reflections = {};
setter_reflections[Constants.STRUCTURED_ATTRS_02.TYPE] = {
  name : "type",
  parser : (v) => v
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.SPEC_VERSION] = {
  name : "specversion",
  parser : (v) => v
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.SOURCE] = {
  name : "source",
  parser: (v) => v
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.ID] = {
  name : "id",
  parser : (v) => v
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.TIME] = {
  name : "time",
  parser : (v) => new Date(Date.parse(v))
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.SCHEMA_URL] = {
  name: "schemaurl",
  parser: (v) => v
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.CONTENT_TYPE] = {
  name: "contenttype",
  parser: (v) => v
};
setter_reflections[Constants.STRUCTURED_ATTRS_02.DATA] = {
  name: "data",
  parser: (v) => v
};

function validate_args(payload, attributes) {
  if(!payload){
    throw {message: "payload is null or undefined"};
  }

  if(!attributes) {
    throw {message: "attributes is null or undefined"};
  }

  if((typeof payload) !== "object" && (typeof payload) !== "string"){
    throw {
      message: "payload must be an object or string",
      errors: [typeof payload]
    };
  }
}

function Receiver(configuration) {

}

Receiver.prototype.check = function(payload, headers) {
  validate_args(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  // Validation Level 1
  if(!allowed_content_types
      .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){
        throw {
          message: "invalid content type",
          errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]
        };
  }

  // No erros! Its contains the minimum required attributes
}

Receiver.prototype.parse = function(payload, headers) {
  this.check(payload, headers);

  var sanity_headers = Commons.sanity_and_clone(headers);

  var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE];

  var parser = parser_by_mime[contentType];
  var event  = parser.parse(payload);
  spec02.check(event);

  var processed_attributes = [];
  var cloudevent = new Cloudevent(Spec02);
  for(attribute in setter_reflections) {
    var setter_name = setter_reflections[attribute].name;
    var parser_fn   = setter_reflections[attribute].parser;

    // invoke the setter function
    cloudevent[setter_name](parser_fn(event[attribute]));

    // to use ahead, for extensions processing
    processed_attributes.push(attribute);
  }

  // Every unprocessed attribute should be an extension
  Array.from(Object.keys(event))
  .filter(attribute => !processed_attributes.includes(attribute))
  .forEach(extension =>
    cloudevent.addExtension(extension, event[extension])
  );

  return cloudevent;
}

module.exports = Receiver;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Task from './Task';

import { ReactComponent as MoreIcon } from './icons/material/expand_more-24px.svg';
import { ReactComponent as LessIcon } from './icons/material/expand_less_black_24dp.svg';

class TaskGroup extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      showDone: false
    }
  }

  render() {
    const done = this.props.note.tasks.filter(task => task.done);
    const todo = this.props.note.tasks.filter(task => !task.done);

    return (

          {this.props.note.title}

        {todo.length > 0 ?

            {todo.map(task => this.renderTask(task))}

          :
          null
        }
        {done.length > 0 ?

            <button className='icon left-aligned full-width' onClick={() => this.setState({ showDone: !this.state.showDone })}>
              { this.state.showDone ?
                <LessIcon /> :
                <MoreIcon />
              }
            </button>

              {done.map(task => this.renderTask(task))}

          :
          null
        }

    );
  }

  renderTask(task) {
    return (
      <Task
        key={task.id}
        note={this.props.note}
        task={task}
        handleTaskChecked={this.props.handleTaskChecked.bind(this)} />
    );
  }
}

export default TaskGroup;
<commit_msg>split too long TaskGroup#render function<commit_after>import React, { Component } from 'react';
import Task from './Task';

import { ReactComponent as MoreIcon } from './icons/material/expand_more-24px.svg';
import { ReactComponent as LessIcon } from './icons/material/expand_less_black_24dp.svg';

class TaskGroup extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      showDone: false
    }
  }

  render() {
    return (

          {this.props.note.title}

        {this.renderTodo()}
        {this.renderDone()}

    );
  }

  renderTodo() {
    const todo = this.props.note.tasks.filter(task => !task.done);

    return (

        {todo.length > 0 ?

            {todo.map(task => this.renderTask(task))}

          :
          null
        }

    );
  }

  renderDone() {
    const done = this.props.note.tasks.filter(task => task.done);

    return (

        {done.length > 0 ?

            <button className='icon left-aligned full-width' onClick={() => this.setState({ showDone: !this.state.showDone })}>
              { this.state.showDone ?
                <LessIcon /> :
                <MoreIcon />
              }
            </button>

              {done.map(task => this.renderTask(task))}

          :
          null
        }

    );
  }

  renderTask(task) {
    return (
      <Task
        key={task.id}
        note={this.props.note}
        task={task}
        handleTaskChecked={this.props.handleTaskChecked.bind(this)} />
    );
  }
}

export default TaskGroup;
<|endoftext|>


<commit_before>(function($) {
"use strict";

if (Echo.AppServer.Dashboard.isDefined("Echo.Apps.Text.Dashboard")) return;

var dashboard = Echo.AppServer.Dashboard.manifest("Echo.Apps.Text.Dashboard");

dashboard.inherits = Echo.Utils.getComponent("Echo.AppServer.Dashboards.AppSettings");

dashboard.config = {
	"ecl": [{
		"component": "Textarea",
		"name": "content",
		"type": "string",
		"config": {
			"title": "Text",
			"inputHeight": 45,
			"desc": "Specifies the text to be displayed. Supports full HTML.",
			"data": {
				"sample": "
Hello!

Feel free to set any text here.
"
			}
		}
	}]
};

dashboard.init = function() {
	this.set("data.instance.config.topic", this._getSharedTopic());
	this._getAllAppKeys();

	this._listenContentChange();

	this.parent();
};

dashboard.methods._getAllAppKeys = function(callback) {
	var self = this;
	var customerId = this.config.get("data.customer.id");
	var request = this.config.get("request");
	var keys = this.get("appkeys");

	callback = callback || $.noop;

	if (keys && keys.length > 0) {
		callback.call(this);
	} else {
		request({
			"endpoint": "customer/" + customerId + "/appkeys",
			"success": function(response) {
				self.set("appkeys", response);
				callback.call(self);
			}
		});
	}
};

dashboard.methods._saveConfig = function() {
	Echo.AppServer.API.request({
		"endpoint": "instance/" + this.get("data.instance.id") + "/update",
		"data": {
			"data": {
				"config": this.get("data.instance.config")
			}
		}
	}).send();
};

dashboard.methods.declareInitialConfig = function() {
	var keys = this.get("appkeys");
	var result = {};
	if (keys && keys[0] && keys[0].key) {
		result.appkey = keys[0].key;
	}
	return result;
};

dashboard.methods._getSharedTopic = function() {
	return this.config.get("context");
};

dashboard.methods._listenContentChange = function() {
	var self = this;
	Echo.AppServer.FrameMessages.subscribe(function(data) {
		if ((data.topic === self._getSharedTopic()) && data.content) {
			data.content = Echo.Apps.Text.Utils.filterContent(data.content, {
				"b": {},
				"i": {},
				"h1": {},
				"h2": {},
				"h3": {},
				"h4": {},
				"p": {},
				"br": {},
				"ul": {},
				"ol": {},
				"li": {},
				"hr": {},
				"a": {
					"href": /^(https?\:)?\/\//
				}
			});
			self.set("data.instance.config.content", data.content);
			self.configurator.setValue({
				"content": data.content
			});
			self._saveConfig();
		}
	});
};

Echo.AppServer.Dashboard.create(dashboard);

})(Echo.jQuery);
<commit_msg>Early returning when conditions not met<commit_after>(function($) {
"use strict";

if (Echo.AppServer.Dashboard.isDefined("Echo.Apps.Text.Dashboard")) return;

var dashboard = Echo.AppServer.Dashboard.manifest("Echo.Apps.Text.Dashboard");

dashboard.inherits = Echo.Utils.getComponent("Echo.AppServer.Dashboards.AppSettings");

dashboard.config = {
	"ecl": [{
		"component": "Textarea",
		"name": "content",
		"type": "string",
		"config": {
			"title": "Text",
			"inputHeight": 45,
			"desc": "Specifies the text to be displayed. Supports full HTML.",
			"data": {
				"sample": "
Hello!

Feel free to set any text here.
"
			}
		}
	}]
};

dashboard.init = function() {
	this.set("data.instance.config.topic", this._getSharedTopic());
	this._getAllAppKeys();

	this._listenContentChange();

	this.parent();
};

dashboard.methods._getAllAppKeys = function(callback) {
	var self = this;
	var customerId = this.config.get("data.customer.id");
	var request = this.config.get("request");
	var keys = this.get("appkeys");

	callback = callback || $.noop;

	if (keys && keys.length > 0) {
		callback.call(this);
	} else {
		request({
			"endpoint": "customer/" + customerId + "/appkeys",
			"success": function(response) {
				self.set("appkeys", response);
				callback.call(self);
			}
		});
	}
};

dashboard.methods._saveConfig = function() {
	Echo.AppServer.API.request({
		"endpoint": "instance/" + this.get("data.instance.id") + "/update",
		"data": {
			"data": {
				"config": this.get("data.instance.config")
			}
		}
	}).send();
};

dashboard.methods.declareInitialConfig = function() {
	var keys = this.get("appkeys");
	var result = {};
	if (keys && keys[0] && keys[0].key) {
		result.appkey = keys[0].key;
	}
	return result;
};

dashboard.methods._getSharedTopic = function() {
	return this.config.get("context");
};

dashboard.methods._listenContentChange = function() {
	var self = this;
	Echo.AppServer.FrameMessages.subscribe(function(data) {
		if (!((data.topic === self._getSharedTopic()) && data.content)) return;
		data.content = Echo.Apps.Text.Utils.filterContent(data.content, {
			"b": {},
			"i": {},
			"h1": {},
			"h2": {},
			"h3": {},
			"h4": {},
			"p": {},
			"br": {},
			"ul": {},
			"ol": {},
			"li": {},
			"hr": {},
			"a": {
				"href": /^(https?\:)?\/\//
			}
		});
		self.set("data.instance.config.content", data.content);
		self.configurator.setValue({
			"content": data.content
		});
		self._saveConfig();
	});
};

Echo.AppServer.Dashboard.create(dashboard);

})(Echo.jQuery);
<|endoftext|>