exports.sexp = function(obj) { if (_.isNull(obj) || _.isUndefined(obj)) { return 'nil'; } else if (obj.toSexp) { return obj.toSexp(); } else if (obj.lispType) { switch (obj.lispType) { case 'string': return exports.string(obj); case 'symbol': return exports.symbol(obj); case 'keyword': return exports.keyword(obj); case 'list': return exports.list(obj); case 'vector': return exports.vector(obj); } throw new Error("Unrecognized lispType: " + util.inspect(obj.lispType)); } else if (_.isString(obj)) { return exports.string(obj); } else if (_.isArray(obj)) { return exports.list(obj); } else if (_.isBoolean(obj)) { return exports.bool(obj); } else if (_.isNumber(obj)) { return exports.number(obj); } else { return exports.alist(obj); } };
'setconfig': function(event) { var configPathString = event.params[1], configKey = _.last(configPathString.split('.')), newOption = event.params[2]; if(!_.include(noChangeConfig, configKey)) { var configPath = getCurrentConfig(configPathString); if(configPath == false || _.isUndefined(configPath.value)) { event.reply("Config key doesn't exist bro"); return; } var currentOption = configPath.value; // Convert to boolean type if config item boolean if(_.isBoolean(currentOption)) { newOption = (newOption == "true"); } if(_.isArray(currentOption)) { event.reply("Config option is an array. Try 'pushconfig'."); } event.reply(configPathString + ": " + currentOption + " -> " + newOption); configPath['user'][configKey] = newOption; dbot.reloadModules(); } else { event.reply("This config option cannot be altered while the bot is running."); } },
'setconfig': function(event) { var configPathString = event.params[1], configKey = _.last(configPathString.split('.')), newOption = event.params[2]; if(!_.include(noChangeConfig, configKey)) { var configPath = getCurrentConfig(configPathString); if(configPath == false || _.isUndefined(configPath.value)) { event.reply(dbot.t("no_config_key")); return; } var currentOption = configPath.value; // Convert to boolean type if config item boolean if(_.isBoolean(currentOption)) { newOption = (newOption == "true"); } if(_.isArray(currentOption)) { event.reply(dbot.t("config_array",{"alternate": "pushconfig"})); } event.reply(configPathString + ": " + currentOption + " -> " + newOption); configPath['user'][configKey] = newOption; dbot.reloadModules(); } else { event.reply(dbot.t("config_lock")); } },
}).forEach(function format (option) { var bool = _.isBoolean(config[option]); if (!bool || config[option]) { args.push('--' + option); if (!bool) args.push(config[option]); } });
_.each(conditions, function(value, key) { var parts = key.trim().split(/ +/); var property = parts[0]; var operation = operationsMap[parts[1]] || '='; if (_.isBoolean(value) || _.isNumber(value)) { return _conditions.push(util.format('"%s" %s %d', property, operation, value)); } if (!_.isArray(value)) { self.params.push(value); return _conditions.push(util.format('"%s" %s %s', property, operation, self.db.placeholder(self.params.length))); } var arrayConditions = []; _.each(value, function(v) { self.params.push(v); arrayConditions.push(self.db.placeholder(self.params.length)); }); _conditions.push(util.format('"%s" %s (%s)', property, operation == '!=' || operation == '<>' ? 'NOT IN' : 'IN', arrayConditions.join(', '))); });
exports.coerce = function(expectedType, value) { var types = { 'string': '', 'number': 0, 'array': [], 'boolean': false }; if (_.isDate(value)) { return value; } if (expectedType === 'date' && !_.isDate(value)) { return (value && new Date(value)) || new Date('1970/1/1'); } if (expectedType && typeof value === 'undefined') { return types[expectedType]; } if (expectedType && typeof value !== 'undefined') { if (expectedType === 'string') { return (value && value.toString()) || ''; } if (expectedType === 'number') { return _.isNumber(_.toInt(value)) ? _.toInt(value) : types.number; } if (expectedType === 'array') { return _.isArray(value) ? value : [ value || '' ]; } if (expectedType === 'boolean') { if (value === 'true') { return true; } if (value === 'false') { return false; } return _.isBoolean(value) ? value : types.boolean; } } return value || ''; };
boolean: function() { return _.isBoolean(this); },
exports.docPredicate = function (result, condition, value, conditions) { //if we have an array of objects, this is a deep traversal //we'll need to use a contains query to be sure we flex the index if(_.isArray(value) && _.isObject(value[0])) { //stringify the passed-in params result.params.push(JSON.stringify(conditions)); result.predicates.push(util.format("body @> $%s", result.params.length + result.offset)); } //if we have equality here, just use a JSON contains else if (condition.operator === '=' && !_.isArray(value)) { //parse the value into stringy JSON var param = {}; param[condition.field]=value; result.params.push(JSON.stringify(param)); result.predicates.push(util.format("body @> $%s", result.params.length + result.offset)); return result; } //comparison stuff - same as method above but this time //we'll be coercing the document key values using pg's :: //not ideal, but it works nicely else if (_.isBoolean(value)) { result.predicates.push( util.format("(body ->> '%s')::boolean %s %s", condition.field, condition.operator, value) ); } else if(_.isDate(value)) { result.params.push(value); result.predicates.push( util.format("(body ->> '%s')::timestamp %s $%d", condition.field, condition.operator, result.params.length + result.offset) ); } else if(_.isNumber(value)) { result.predicates.push( util.format("(body ->> '%s')::decimal %s %d", condition.field, condition.operator, value) ); } //anything non-array handling else if (!_.isArray(value)) { result.params.push(value); result.predicates.push( util.format("(body ->> '%s') %s $%s", condition.field, condition.operator, result.params.length + result.offset) ); } else { var arrayConditions = []; _.each(value, function(v) { result.params.push(v); arrayConditions.push("$" + (result.params.length + result.offset)); }); condition.operator = condition.operator === '=' ? 'IN' : 'NOT IN'; result.predicates.push( util.format("(body ->> '%s') %s (%s)", condition.field, condition.operator, arrayConditions.join(', ')) ); } return result; };
console.log(_.has({a:1, b:2, c:3}, 'b')); //true // isEqual: 判断两个对象是值相等 var moe = {name:'moe', b:[1,2,3]}; var clone = {name:'moe', b:[1,2,3]}; console.log(moe==clone);//false console.log(_.isEqual(moe, clone));//true //判断对象类型以下都为空 console.log(_.isEmpty({})); //如果object里没包含任何东西,将返回true console.log(_.isArray([1,2,3])); console.log(_.isObject({})); console.log((function(){ return _.isArguments(arguments); })(1, 2, 3)); console.log(_.isFunction(console.log)); console.log(_.isString("moe")); console.log(_.isNumber(8.4 * 5)); console.log(_.isFinite(-101)); console.log(_.isBoolean(true)); console.log(_.isDate(new Date())); console.log(_.isNaN(NaN)); console.log(_.isNull(null)); console.log(_.isUndefined(undefined)); // invert _.invert(object) // 返回一个object的副本,并且里面的键和值是对调的,要使之有效,必须确保object里所有的值都是唯一的且可以序列号成字符串 console.log(_.invert({a:'b', c:'d', e:'f'})); // { b: 'a', d: 'c', f: 'e' } // pairs _.pairs(object) // 把一个对象转换成一个[key, value]形式的数组 console.log(_.pairs({one:1, two:2, three: 3})); // [ [ 'one', 1 ], [ 'two', 2 ], [ 'three', 3 ] ] // values _.values(object) // 获取object对象的所有属性值
var typecast = function(value, originalValue, properties) { // Allow transform to manipulate raw properties. if(properties.transform) { value = properties.transform.call(this, value, originalValue, properties); } switch(properties.type) { case 'string': // Reject if object or array. if(_.isObject(value) || _.isArray(value)) { throw new SetterError('String type cannot typecast Object or Array types.', value, originalValue, properties); } // If index is being set with null or undefined, set value and end. if(_.isUndefined(value) || value === null) { return value; } // Typecast to String. value = value + ''; // If stringTransform function is defined, use. // This is used before we do validation checks (except to be sure we have a string at all). if(properties.stringTransform) { value = properties.stringTransform.call(this, value, originalValue, properties); } // If clip property & maxLength properties are set, the string should be clipped. // This is basically a shortcut property that could be done with stringTransform. if(properties.clip && !_.isUndefined(properties.maxLength)) { value = value.substr(0, properties.maxLength); } // If enum is being used, be sure the value is within definition. if(_.isArray(properties.enum) && properties.enum.indexOf(value) === -1) { throw new SetterError('String does not exist in enum list.', value, originalValue, properties); } // If minLength is defined, check to be sure the string is > minLength. if(!_.isUndefined(properties.minLength) && value.length < properties.minLength) { throw new SetterError('String length too short to meet minLength requirement.', value, originalValue, properties); } // If maxLength is defined, check to be sure the string is < maxLength. if(!_.isUndefined(properties.maxLength) && value.length > properties.maxLength) { throw new SetterError('String length too long to meet maxLength requirement.', value, originalValue, properties); } // If regex is defined, check to be sure the string matches the regex pattern. if(properties.regex && !properties.regex.test(value)) { throw new SetterError('String does not match regular expression pattern.', value, originalValue, properties); } return value; break; case 'number': // Set values for boolean. if(_.isBoolean(value)) { value = value ? 1 : 0; } // Reject if array, object, or not numeric. if( _.isArray(value) || _.isObject(value) || !isNumeric(value)) { throw new SetterError('Number type cannot typecast Array or Object types.', value, originalValue, properties); } // Typecast to number. value = value * 1; // Transformation after typecasting but before validation and filters. if(properties.numberTransform) { value = properties.numberTransform.call(this, value, originalValue, properties); } if(!_.isUndefined(properties.min) && value < properties.min) { throw new SetterError('Number is too small to meet min requirement.', value, originalValue, properties); } if(!_.isUndefined(properties.max) && value > properties.max) { throw new SetterError('Number is too big to meet max requirement.', value, originalValue, properties); } return value; break; case 'boolean': // If is String and is 'false', return false. if(value === 'false') { return false; } // If is Number, <0 is true and >0 is false. if(isNumeric(value)) { return (value * 1) > 0 ? true : false; } // Use Javascript to eval and return boolean. value = value ? true : false; // Transformation after typecasting but before validation and filters. if(properties.booleanTransform) { value = properties.booleanTransform.call(this, value, originalValue, properties); } return value; break; case 'array': // If it's an object, typecast to an array and return array. if(_.isObject(value)) { value = _.toArray(value); } // Reject if not array. if(!_.isArray(value)) { throw new SetterError('Array type cannot typecast non-Array types.', value, originalValue, properties); } // Arrays are never set directly. // Instead, the values are copied over to the existing SchemaArray instance. // The SchemaArray is initialized immediately and will always exist. originalValue.length = 0; _.each(value, function(arrayValue) { originalValue.push(arrayValue); }); return originalValue; break; case 'object': // If it's not an Object, reject. if(!_.isObject(value)) { throw new SetterError('Object type cannot typecast non-Object types.', value, originalValue, properties); } // If object is schema object and an entirely new object was passed, clear values and set. // This preserves the object instance. if(properties.objectType) { // The object will usually exist because it's initialized immediately for deep access within SchemaObjects. // However, in the case of Array elements, it will not exist. var schemaObject; if(!_.isUndefined(originalValue)) { // Clear existing values. schemaObject = originalValue; schemaObject.clear(); } else { // The SchemaObject doesn't exist yet. Let's initialize a new one. // This is used for Array types. schemaObject = new properties.objectType; } // Copy value to SchemaObject and set value to SchemaObject. _.each(value, function(v, k) { schemaObject[k] = v; }); value = schemaObject; } // Otherwise, it's OK. return value; break; case 'date': // Reject if object, array or boolean. if(!_.isDate(value) && !_.isString(value) && !_.isNumber(value)) { throw new SetterError('Date type cannot typecast Array or Object types.', value, originalValue, properties); } // Attempt to parse string value with Date.parse (which returns number of milliseconds). if(_.isString(value)) { value = Date.parse(value); } // If is timestamp, convert to Date. if(_.isNumber(value)) { value = new Date((value + '').length > 10 ? value : value * 1000); } // If the date couldn't be parsed, do not modify index. if(value == 'Invalid Date' || !_.isDate(value)) { throw new SetterError('Could not parse date.', value, originalValue, properties); } // Transformation after typecasting but before validation and filters. if(properties.dateTransform) { value = properties.dateTransform.call(this, value, originalValue, properties); } return value; break; default: return value; break; } };
socket.on('things', function() { var args = Array.prototype.slice.call(arguments); var fn = args.pop() || function() {} , data = args.shift(); if (!data && !_.isFunction(fn)) { data = fn; fn = function() {}; } if (!data) { args = { query: data, user: user }; Thing.fetch( args, function(err, things) { if (err) { fn(err); return; } fn(null, things); }); return; } if (_.isString(data)) { args = { user: user, key: data }; Thing.get( args, function(err, thing) { if (err) { fn(err); return; } fn(null, thing); }); return; } if (toString.call(data) !== '[object Object]' || _.keys(data).length < 1) { fn({ message: 'that doesn\'t look like a valid object', code: 400 }); return; } if (_.isUndefined(data.key)) { args = { payload: data, user: user }; Thing.add( args, function(err, thing) { if (err) { fn(err); return; } fn(null, thing); } ); return; } if (!_.isUndefined(data.changed) && _.isBoolean(data.changed) && data.changed) { args = { payload: data, user: user }; Thing.modify( args, function(err, thing) { if (err) { res.send(err.code, err.message); return; } res.json(thing); } ); return; } if (!_.isUndefined(data.deleted) && _.isBoolean(data.deleted) && data.deleted) { args = { key: data.key, user: user }; Thing.remove( args, function(err) { if (err) { fn(err); return; } fn(null); }); return; } fn({ message: 'seems like you did an invalid request', code: 400 }); return; });