Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

pathval

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pathval - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

pathval.js

357

index.js

@@ -0,126 +1,137 @@

'use strict';
/* !
* Chai - pathval utility
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* @see https://github.com/logicalparadox/filtr
* MIT Licensed
*/
var type = require('type-detect');
/**
* ### .get(obj, path)
* ### .hasProperty(object, name)
*
* Retrieve the value in an object given a string path.
* This allows checking whether an object has
* named property or numeric array index.
*
* ```js
* var obj = {
* prop1: {
* Basically does the same thing as the `in`
* operator but works properly with natives
* and null/undefined values.
*
* var obj = {
* arr: ['a', 'b', 'c']
* , str: 'Hello'
* }
* , prop2: {
* arr: [ { nested: 'Universe' } ]
* , str: 'Hello again!'
* }
* };
* ```
*
* The following would be the results.
*
* ```js
* var properties = require('tea-properties');
* properties.get(obj, 'prop1.str'); // Hello
* properties.get(obj, 'prop1.att[2]'); // b
* properties.get(obj, 'prop2.arr[0].nested'); // Universe
* ```
* hasProperty(obj, 'str'); // true
* hasProperty(obj, 'constructor'); // true
* hasProperty(obj, 'bar'); // false
*
* @param {Object} object
* @param {String} path
* @return {Object} value or `undefined`
*/
exports.get = function(obj, path) {
var parsed = exports.parse(path);
return getPathValue(parsed, obj);
};
/**
* ### .set(path, value, object)
* hasProperty(obj.str, 'length'); // true
* hasProperty(obj.str, 1); // true
* hasProperty(obj.str, 5); // false
*
* Define the value in an object at a given string path.
* hasProperty(obj.arr, 'length'); // true
* hasProperty(obj.arr, 2); // true
* hasProperty(obj.arr, 3); // false
*
* ```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
* @param {String|Number} name
* @returns {Boolean} whether it exists
* @namespace Utils
* @name hasProperty
* @api public
*/
exports.set = function(obj, path, val) {
var parsed = exports.parse(path);
setPathValue(parsed, val, obj);
var literals = {
'number': Number,
'string': String,
};
function hasProperty(obj, name) {
var objType = type(obj);
// Bad Object, obviously no props at all
if (objType === 'null' || objType === 'undefined') {
return false;
}
/*!
// The `in` operator does not work with certain literals
// box these before the check
if (literals[objType] && typeof obj !== 'object') {
obj = new literals[objType](obj);
}
return name in obj;
}
/* !
* ## parsePath(path)
*
* Helper function used to parse string object
* paths. Use in conjunction with `getPathValue`.
* paths. Use in conjunction with `internalGetPathValue`.
*
* var parsed = parsePath('myobject.property.subprop');
* var parsed = parsePath('myobject.property.subprop');
*
* ### Paths:
*
* * Can be as near infinitely deep and nested
* * 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
*/
exports.parse = function(path) {
var str = (path || '').replace(/\[/g, '.[');
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 parts.map(function(value) {
var re = /\[(\d+)\]$/
, mArr = re.exec(value)
if (mArr) return { i: parseFloat(mArr[1]) };
else return { p: value };
return parsed;
});
};
}
/*!
* Companion function for `parsePath` that returns
/* !
* ## internalGetPathValue(obj, parsed[, pathDepth])
*
* Helper companion function for `.parsePath` that returns
* the value located at the parsed address.
*
* var value = getPathValue(parsed, obj);
* var value = getPathValue(obj, parsed);
*
* @param {Object} object to search against
* @param {Object} parsed definition from `parsePath`.
* @param {Object} object to search against
* @param {Number} depth (nesting level) of the property we want to retrieve
* @returns {Object|Undefined} value
* @api private
*/
function getPathValue(parsed, obj) {
var tmp = obj;
var res;
function internalGetPathValue(obj, parsed, pathDepth) {
var temporaryValue = obj;
var res = null;
pathDepth = (typeof pathDepth === 'undefined' ? parsed.length : pathDepth);
for (var i = 0, l = parsed.length; i < l; i++) {
for (var i = 0; i < pathDepth; i++) {
var part = parsed[i];
if (tmp) {
if (defined(part.p)) tmp = tmp[part.p];
else if (defined(part.i)) tmp = tmp[part.i];
if (i == (l - 1)) res = tmp;
} else {
res = undefined;
if (temporaryValue) {
if (typeof part.p === 'undefined') {
temporaryValue = temporaryValue[part.i];
} else {
temporaryValue = temporaryValue[part.p];
}
if (i === (pathDepth - 1)) {
res = temporaryValue;
}
}

@@ -130,58 +141,164 @@ }

return res;
};
}
/*!
/* !
* ## internalSetPathValue(obj, value, parsed)
*
* Companion function for `parsePath` that sets
* the value located at a parsed address.
*
* setPathValue(parsed, 'value', obj);
* internalSetPathValue(obj, 'value', parsed);
*
* @param {Object} object to search and define on
* @param {*} value to use upon set
* @param {Object} parsed definition from `parsePath`
* @param {*} value to use upon set
* @param {Object} object to search and define on
* @api private
*/
function setPathValue(parsed, val, obj) {
var tmp = obj;
var i = 0;
var l = parsed.length;
var part;
for (; i < l; i++) {
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 (defined(tmp) && i == (l - 1)) {
var x = defined(part.p) ? part.p : part.i;
tmp[x] = val;
} else if (defined(tmp)) {
if (defined(part.p) && tmp[part.p]) {
tmp = tmp[part.p];
} else if (defined(part.i) && tmp[part.i]) {
tmp = tmp[part.i];
} else {
var next = parsed[i + 1];
var x = defined(part.p) ? part.p : part.i;
var y = defined(next.p) ? {} : [];
tmp[x] = y;
tmp = tmp[x];
}
// 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 (i == (l - 1)) tmp = val;
else if (defined(part.p)) tmp = {};
else if (defined(part.i)) tmp = [];
// 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];
}
}
};
}
/*!
* Check if `val` is defined.
/**
* ### .getPathInfo(object, path)
*
* @param {Mixed} val
* @returns {Boolean} `true` if defined
* 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 defined(val) {
return !(!val && 'undefined' === typeof val);
function setPathValue(obj, path, val) {
var parsed = parsePath(path);
internalSetPathValue(obj, val, parsed);
}
module.exports = {
hasProperty: hasProperty,
getPathInfo: getPathInfo,
getPathValue: getPathValue,
setPathValue: setPathValue,
};
{
"name": "pathval",
"version": "0.1.1",
"description": "Object value retrieval given a string path",
"homepage": "https://github.com/chaijs/pathval",
"keywords": [
"pathval",
"value retrieval",
"chai util"
],
"license": "MIT",
"author": "Veselin Todorov <hi@vesln.com>",
"files": [
"index.js",
"pathval.js"
],
"main": "./index.js",
"homepage": "https://github.com/chaijs/pathval",
"scripts": {
"test": "hydro",
"coverage": "istanbul cover _hydro",
"coveralls": "istanbul cover _hydro --report lcovonly && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"test-readme": "jsmd README.md"
},
"repository": {
"type": "git",
"url": "https://github.com/chaijs/pathval"
"url": "git+ssh://git@github.com/chaijs/pathval.git"
},
"scripts": {
"build": "browserify --bare $npm_package_main --standalone pathval -o pathval.js",
"lint": "eslint --ignore-path .gitignore .",
"prepublish": "npm run build",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"pretest": "npm run lint",
"test": "npm run test:node && npm run test:browser && npm run upload-coverage",
"test:browser": "karma start --singleRun=true",
"test:node": "istanbul cover _mocha",
"upload-coverage": "lcov-result-merger 'coverage/**/lcov.info' | coveralls; exit 0"
},
"config": {
"ghooks": {
"commit-msg": "validate-commit-msg"
}
},
"eslintConfig": {
"extends": [
"strict/es5"
],
"env": {
"es6": true
},
"globals": {
"HTMLElement": false
},
"rules": {
"complexity": 0,
"max-statements": 0
}
},
"dependencies": {
"type-detect": "^2.0.1"
},
"devDependencies": {
"coveralls": "~2.3.0",
"istanbul": "~0.1.44",
"jsmd": "~0.2.0",
"simple-assert": "~1.0.0",
"hydro": "~0.8.7",
"hydro-file-suite": "0.0.1",
"hydro-doc": "0.0.2",
"hydro-bdd": "0.0.3"
"browserify": "^13.0.0",
"browserify-istanbul": "^1.0.0",
"coveralls": "2.11.9",
"eslint": "^2.4.0",
"eslint-config-strict": "^8.5.0",
"eslint-plugin-filenames": "^0.2.0",
"ghooks": "^1.0.1",
"istanbul": "^0.4.2",
"karma": "^0.13.22",
"karma-browserify": "^5.0.2",
"karma-coverage": "^0.5.5",
"karma-mocha": "^0.2.2",
"karma-phantomjs-launcher": "^1.0.0",
"karma-sauce-launcher": "^0.3.1",
"lcov-result-merger": "^1.0.2",
"mocha": "^2.4.5",
"phantomjs-prebuilt": "^2.1.5",
"semantic-release": "^4.3.5",
"simple-assert": "^1.0.0",
"travis-after-all": "^1.4.4",
"validate-commit-msg": "^2.3.1"
},
"author": "Veselin Todorov <hi@vesln.com>",
"license": "MIT"
}
"engines": {
"node": "*"
},
"version": "0.2.0"
}

@@ -1,103 +0,145 @@

[![NPM version](https://badge.fury.io/js/pathval.png)](http://badge.fury.io/js/pathval)
[![Build Status](https://secure.travis-ci.org/chaijs/pathval.png)](http://travis-ci.org/chaijs/pathval)
[![Coverage Status](https://coveralls.io/repos/chaijs/pathval/badge.png?branch=master)](https://coveralls.io/r/chaijs/pathval?branch=master)
[![Code Climate](https://codeclimate.com/github/chaijs/pathval.png)](https://codeclimate.com/github/chaijs/pathval)
<h1 align=center>
<a href="http://chaijs.com" title="Chai Documentation">
<img alt="ChaiJS" src="http://chaijs.com/img/chai-logo.png"/> pathval
</a>
</h1>
# pathval
<p align=center>
Tool for Object value retrieval given a string path for <a href="http://nodejs.org">node</a> and the browser.
</p>
## Usage
<p align=center>
<a href="./LICENSE">
<img
alt="license:mit"
src="https://img.shields.io/badge/license-mit-green.svg?style=flat-square"
/>
</a>
<a href="https://github.com/chaijs/pathval/releases">
<img
alt="tag:?"
src="https://img.shields.io/github/tag/chaijs/pathval.svg?style=flat-square"
/>
</a>
<a href="https://travis-ci.org/chaijs/pathval">
<img
alt="build:?"
src="https://img.shields.io/travis/chaijs/pathval/master.svg?style=flat-square"
/>
</a>
<a href="https://coveralls.io/r/chaijs/pathval">
<img
alt="coverage:?"
src="https://img.shields.io/coveralls/chaijs/pathval/master.svg?style=flat-square"
/>
</a>
<a href="https://www.npmjs.com/packages/pathval">
<img
alt="npm:?"
src="https://img.shields.io/npm/v/pathval.svg?style=flat-square"
/>
</a>
<a href="https://www.npmjs.com/packages/pathval">
<img
alt="dependencies:?"
src="https://img.shields.io/npm/dm/pathval.svg?style=flat-square"
/>
</a>
<a href="">
<img
alt="devDependencies:?"
src="https://img.shields.io/david/chaijs/pathval.svg?style=flat-square"
/>
</a>
<br/>
<a href="https://saucelabs.com/u/chaijs-pathval">
<img
alt="Selenium Test Status"
src="https://saucelabs.com/browser-matrix/chaijs-pathval.svg"
/>
</a>
<br>
<a href="https://chai-slack.herokuapp.com/">
<img
alt="Join the Slack chat"
src="https://img.shields.io/badge/slack-join%20chat-E2206F.svg?style=flat-square"
/>
</a>
<a href="https://gitter.im/chaijs/chai">
<img
alt="Join the Gitter chat"
src="https://img.shields.io/badge/gitter-join%20chat-D0104D.svg?style=flat-square"
/>
</a>
</p>
```
var props = require('pathval');
```
## What is pathval?
Given:
Pathval is a module which you can use to retrieve or set an Object's property for a given `String` path.
```js
var obj = {
prop1: {
arr: ['a', 'b', 'c']
, str: 'Hello'
}
, prop2: {
arr: [ { nested: 'Universe' } ]
, str: 'Hello again!'
}
}
## Installation
var arr = [ { foo: 'bar' } ];
```
### Node.js
Expect:
`pathval` is available on [npm](http://npmjs.org). To install it, type:
<!-- js
var props = require('./');
-->
$ npm install pathval
#### get
### Browsers
```js
props.get(obj, 'prop1.str'); // => "Hello"
props.get(obj, 'prop1.arr[2]'); // => "c"
props.get(obj, 'prop2.arr[0].nested'); // => "Universe"
You can also use it within the browser; install via npm and use the `pathval.js` file found within the download. For example:
props.get(arr, '[0].foo'); // => "bar"
props.get(undefined, 'doesnt.matter'); // => undefined
props.get({}, 'doesnt.exist'); // => undefined
```html
<script src="./node_modules/pathval/pathval.js"></script>
```
#### set
## Usage
The primary export of `pathval` is an object which has the following methods:
* `hasProperty(object, name)` - Checks whether an `object` has `name`d property or numeric array index.
* `getPathInfo(object, path)` - Returns an object with info indicating the value of the `parent` of that path, the `name ` of the property we're retrieving and its `value`.
* `getPathValue(object, path)` - Retrieves the value of a property at a given `path` inside an `object`'.
* `setPathValue(object, path, value)` - Sets the `value` of a property at a given `path` inside an `object`'.
```js
props.set(obj, 'hello.universe', 'properties');
props.set(obj, 'hello.universe[1].properties', 'galaxy');
props.set(obj, 'hello', 'universe');
props.set(obj, 'hello[0]', 1);
props.set(obj, 'hello[2]', 3);
var pathval = require('pathval');
```
## Installation
#### .hasProperty(object, name)
```bash
npm install pathval
```js
var pathval = require('pathval');
var obj = { prop: 'a value' };
pathval.hasProperty(obj, 'prop'); // true
```
## Tests
#### .getPathInfo(object, path)
### Running the tests
```js
var pathval = require('pathval');
```bash
$ npm test
var obj = { earth: { country: 'Brazil' } };
pathval.getPathInfo(obj, 'earth.country'); // { parent: { country: 'Brazil' }, name: 'country', value: 'Brazil', exists: true }
```
### Test coverage
#### .getPathValue(object, path)
```bash
$ npm run-script coverage
```
```js
var pathval = require('pathval');
### Readme tests
```bash
$ npm run-script test-readme
var obj = { earth: { country: 'Brazil' } };
pathval.getPathValue(obj, 'earth.country'); // 'Brazil'
```
## License
#### .setPathValue(object, path, value)
MIT License
```js
var pathval = require('pathval');
Copyright (c) 2011-2013 Jake Luer jake@alogicalparadox.com
var obj = { earth: { country: 'Brazil' } };
pathval.setPathValue(obj, 'earth.country', 'USA');
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
obj.earth.country; // 'USA'
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc