UNPKG

luhn-generator

Version:

A generator of numbers that passes the validation of Luhn algorithm or Luhn formula, also known as the 'modulus 10' or 'mod 10' algorithm

292 lines (268 loc) 7.66 kB
'use strict'; /* ! * Chai - pathval utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * @see https://github.com/logicalparadox/filtr * MIT Licensed */ /** * ### .hasProperty(object, name) * * This allows checking whether an object has own * or inherited from prototype chain named property. * * Basically does the same thing as the `in` * operator but works properly with null/undefined values * and other primitives. * * var obj = { * arr: ['a', 'b', 'c'] * , str: 'Hello' * } * * The following would be the results. * * hasProperty(obj, 'str'); // true * hasProperty(obj, 'constructor'); // true * hasProperty(obj, 'bar'); // false * * hasProperty(obj.str, 'length'); // true * hasProperty(obj.str, 1); // true * hasProperty(obj.str, 5); // false * * hasProperty(obj.arr, 'length'); // true * hasProperty(obj.arr, 2); // true * hasProperty(obj.arr, 3); // false * * @param {Object} object * @param {String|Symbol} name * @returns {Boolean} whether it exists * @namespace Utils * @name hasProperty * @api public */ function hasProperty(obj, name) { if (typeof obj === 'undefined' || obj === null) { return false; } // The `in` operator does not work with primitives. return name in Object(obj); } /* ! * ## parsePath(path) * * Helper function used to parse string object * paths. Use in conjunction with `internalGetPathValue`. * * var parsed = parsePath('myobject.property.subprop'); * * ### Paths: * * * Can be infinitely deep and nested. * * Arrays are also valid using the formal `myobject.document[3].property`. * * Literal dots and brackets (not delimiter) must be backslash-escaped. * * @param {String} path * @returns {Object} parsed * @api private */ function parsePath(path) { var str = path.replace(/([^\\])\[/g, '$1.['); var parts = str.match(/(\\\.|[^.]+?)+/g); return parts.map(function mapMatches(value) { var regexp = /^\[(\d+)\]$/; var mArr = regexp.exec(value); var parsed = null; if (mArr) { parsed = { i: parseFloat(mArr[1]) }; } else { parsed = { p: value.replace(/\\([.\[\]])/g, '$1') }; } return parsed; }); } /* ! * ## internalGetPathValue(obj, parsed[, pathDepth]) * * Helper companion function for `.parsePath` that returns * the value located at the parsed address. * * var value = getPathValue(obj, parsed); * * @param {Object} object to search against * @param {Object} parsed definition from `parsePath`. * @param {Number} depth (nesting level) of the property we want to retrieve * @returns {Object|Undefined} value * @api private */ function internalGetPathValue(obj, parsed, pathDepth) { var temporaryValue = obj; var res = null; pathDepth = (typeof pathDepth === 'undefined' ? parsed.length : pathDepth); for (var i = 0; i < pathDepth; i++) { var part = parsed[i]; if (temporaryValue) { if (typeof part.p === 'undefined') { temporaryValue = temporaryValue[part.i]; } else { temporaryValue = temporaryValue[part.p]; } if (i === (pathDepth - 1)) { res = temporaryValue; } } } return res; } /* ! * ## internalSetPathValue(obj, value, parsed) * * Companion function for `parsePath` that sets * the value located at a parsed address. * * internalSetPathValue(obj, 'value', parsed); * * @param {Object} object to search and define on * @param {*} value to use upon set * @param {Object} parsed definition from `parsePath` * @api private */ function internalSetPathValue(obj, val, parsed) { var tempObj = obj; var pathDepth = parsed.length; var part = null; // Here we iterate through every part of the path for (var i = 0; i < pathDepth; i++) { var propName = null; var propVal = null; part = parsed[i]; // If it's the last part of the path, we set the 'propName' value with the property name if (i === (pathDepth - 1)) { propName = typeof part.p === 'undefined' ? part.i : part.p; // Now we set the property with the name held by 'propName' on object with the desired val tempObj[propName] = val; } else if (typeof part.p !== 'undefined' && tempObj[part.p]) { tempObj = tempObj[part.p]; } else if (typeof part.i !== 'undefined' && tempObj[part.i]) { tempObj = tempObj[part.i]; } else { // If the obj doesn't have the property we create one with that name to define it var next = parsed[i + 1]; // Here we set the name of the property which will be defined propName = typeof part.p === 'undefined' ? part.i : part.p; // Here we decide if this property will be an array or a new object propVal = typeof next.p === 'undefined' ? [] : {}; tempObj[propName] = propVal; tempObj = tempObj[propName]; } } } /** * ### .getPathInfo(object, path) * * This allows the retrieval of property info in an * object given a string path. * * The path info consists of an object with the * following properties: * * * parent - The parent object of the property referenced by `path` * * name - The name of the final property, a number if it was an array indexer * * value - The value of the property, if it exists, otherwise `undefined` * * exists - Whether the property exists or not * * @param {Object} object * @param {String} path * @returns {Object} info * @namespace Utils * @name getPathInfo * @api public */ function getPathInfo(obj, path) { var parsed = parsePath(path); var last = parsed[parsed.length - 1]; var info = { parent: parsed.length > 1 ? internalGetPathValue(obj, parsed, parsed.length - 1) : obj, name: last.p || last.i, value: internalGetPathValue(obj, parsed), }; info.exists = hasProperty(info.parent, info.name); return info; } /** * ### .getPathValue(object, path) * * This allows the retrieval of values in an * object given a string path. * * var obj = { * prop1: { * arr: ['a', 'b', 'c'] * , str: 'Hello' * } * , prop2: { * arr: [ { nested: 'Universe' } ] * , str: 'Hello again!' * } * } * * The following would be the results. * * getPathValue(obj, 'prop1.str'); // Hello * getPathValue(obj, 'prop1.att[2]'); // b * getPathValue(obj, 'prop2.arr[0].nested'); // Universe * * @param {Object} object * @param {String} path * @returns {Object} value or `undefined` * @namespace Utils * @name getPathValue * @api public */ function getPathValue(obj, path) { var info = getPathInfo(obj, path); return info.value; } /** * ### .setPathValue(object, path, value) * * Define the value in an object at a given string path. * * ```js * var obj = { * prop1: { * arr: ['a', 'b', 'c'] * , str: 'Hello' * } * , prop2: { * arr: [ { nested: 'Universe' } ] * , str: 'Hello again!' * } * }; * ``` * * The following would be acceptable. * * ```js * var properties = require('tea-properties'); * properties.set(obj, 'prop1.str', 'Hello Universe!'); * properties.set(obj, 'prop1.arr[2]', 'B'); * properties.set(obj, 'prop2.arr[0].nested.value', { hello: 'universe' }); * ``` * * @param {Object} object * @param {String} path * @param {Mixed} value * @api private */ function setPathValue(obj, path, val) { var parsed = parsePath(path); internalSetPathValue(obj, val, parsed); return obj; } module.exports = { hasProperty: hasProperty, getPathInfo: getPathInfo, getPathValue: getPathValue, setPathValue: setPathValue, };