Skip to content

Commit

Permalink
Final polish
Browse files Browse the repository at this point in the history
  • Loading branch information
vonthar committed Aug 21, 2016
1 parent c77b2e9 commit d695290
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 73 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
.eslintrc.json
.nyc_output
coverage
node_modules
npm-debug.log
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: node_js
language: node_js
node_js:
- node
after_success: npm run coverage
sudo: false
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Mozilla Public License Version 2.0
Mozilla Public License Version 2.0
==================================

### 1. Definitions
Expand Down
64 changes: 39 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,65 @@
dotpath-strict
==============
node-dotpath-strict
===============================================================================
[![NPM Package](https://img.shields.io/npm/v/dotpath-strict.svg)](https://www.npmjs.org/package/dotpath-strict)
[![Build Status](https://travis-ci.org/vonthar/node-dotpath-strict.svg?branch=master)](https://travis-ci.org/vonthar/node-dotpath-strict/branches)
[![Coverage Status](https://coveralls.io/repos/github/vonthar/node-dotpath-strict/badge.svg?branch=master)](https://coveralls.io/github/vonthar/node-dotpath-strict?branch=master)
[![Dependency Status](https://david-dm.org/vonthar/node-dotpath-strict.svg)](https://david-dm.org/vonthar/node-dotpath-strict)

### Aren't there a million of these already?
I couldn't find one that distinguishes between a property that is unset and one that is
set to undefined so I made this. It throws an error when attempting to access a
nonexisting property. Supports basic dot notation and numeric brackets.

I couldn't find one that distinguishes between a property that is unset and one that is set to undefined so I made this one. It throws an error when attempting to access a nonexisting property. Supports basic dot notation and numeric brackets.

**Example**
```js
var dotPath = require("dotpath-strict");
var post = { title: "Readme", author: { firstName: "Hugh", lastName: "Mungus" } };
dotPath(post, "author.firstName");
//"Hugh"
```
Installation
------------
`npm i dotpath-strict`

Usage
-----
### dotpath(object, path, [value]) => value
API Reference
-------------
<a name="exp_module_dotpath-strict--dotPath"></a>

__Arguments__
* `object`
* `path`
* `value` *optional* Set property to this value
### dotPath(object, path, [value]) ⇒ <code>\*</code> ⏏
**Kind**: Exported function
**Throws**:

Example
-------
- <code>ReferenceError</code>
- <code>TypeError</code>

**Params**

- object <code>Object</code>
- path <code>string</code>
- [value] <code>string</code> - Set property to this value

**Example**
```js
var obj = { a: { aa: 1, ab: [ "1", "2" ] }, b: undefined, c: null };
var dotpath = require("dotpath-strict");
dotpath(obj, "a.aa");
dotPath(obj, "a.aa");
//1
dotpath(obj, "a.ab[1]");
dotPath(obj, "a.ab[1]");
//"2"
dotpath(obj, "b");
dotPath(obj, "b");
//undefined
dotpath(obj, "c");
dotPath(obj, "c");
//null
dotpath(obj, "d");
dotPath(obj, "d");
//ReferenceError: d is not defined
dotpath(obj, "d", "2");
dotPath(obj, "d", "2");
//"2"
dotpath(obj, "d.e", 3);
dotPath(obj, "d.e", 3);
//TypeError: d is not an object
dotpath(obj, "d", { e: 3 });
dotPath(obj, "d", { e: 3 });
//{ e: 3 }
dotpath(obj, "d.e");
dotPath(obj, "d.e");
//3
```

License
-------
MPL 2.0

21 changes: 14 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dotpath-strict",
"version": "1.0.1",
"version": "1.0.4",
"description": "Get or set property value by dotpath string, throws on failure.",
"keywords": [
"object",
Expand All @@ -20,20 +20,27 @@
"homepage": "https://github.com/vonthar/node-dotpath-strict",
"repository": {
"type": "git",
"url": "git://github.com/vonthar/node-dotpath-strict.git"
"url": "git+https://github.com/vonthar/node-dotpath-strict.git"
},
"bugs": {
"url": "https://github.com/vonthar/node-dotpath-strict/issues"
},
"main": "src/dotpath.js",
"scripts": {
"test": "node test/dotpath-tests.js",
"lint": "eslint ."
},
"dependencies": {
"test": "nyc tape test/*.js",
"coverage": "npm test && nyc report --reporter=text-lcov | coveralls",
"lint": "eslint -c node_modules/@vonthar/pkgdev/etc/eslintrc.json src/*.js",
"docs": "jsdoc2md -p list -r list -t node_modules/@vonthar/pkgdev/etc/jsdoc2md.hbs src/*.js > README.md",
"preversion": "npm test && git add .",
"postversion": "git push -u origin master && git push origin master --tags && npm publish"
},
"dependencies": {},
"devDependencies": {
"@vonthar/pkgdev": "git+https://github.com/vonthar/pkgdev.git",
"coveralls": "^2.11.12",
"eslint": "^2.11.1",
"eslint-config-google": "^0.5.0"
"eslint-config-xo": "^0.15.3",
"nyc": "^8.1.0",
"tape": "^4.6.0"
}
}
85 changes: 76 additions & 9 deletions src/dotpath.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,73 @@
"use strict";
"use strict";

/**
* ### Aren't there a million of these already?
* I couldn't find one that distinguishes between a property that is unset and one that is
* set to undefined so I made this. It throws an error when attempting to access a
* nonexisting property. Supports basic dot notation and numeric brackets.
* @module dotpath-strict
* @example
* var dotPath = require("dotpath-strict");
* var post = { title: "Readme", author: { firstName: "Hugh", lastName: "Mungus" } };
* dotPath(post, "author.firstName");
* //"Hugh"
*/
module.exports = dotPath;

var separator = /\.|\[(\d+)\]/g;

module.exports = function (object, path, value) {
var separator = /\.|\[(\d+)\]/g;
/**
* @alias module:dotpath-strict
* @param {Object} object
* @param {string} path
* @param {string=} value - Set property to this value
* @returns {*}
* @throws {ReferenceError}
* @throws {TypeError}
* @example
* var obj = { a: { aa: 1, ab: [ "1", "2" ] }, b: undefined, c: null };
* dotPath(obj, "a.aa");
* //1
* dotPath(obj, "a.ab[1]");
* //"2"
* dotPath(obj, "b");
* //undefined
* dotPath(obj, "c");
* //null
* dotPath(obj, "d");
* //ReferenceError: d is not defined
* dotPath(obj, "d", "2");
* //"2"
* dotPath(obj, "d.e", 3);
* //TypeError: d is not an object
* dotPath(obj, "d", { e: 3 });
* //{ e: 3 }
* dotPath(obj, "d.e");
* //3
*/
function dotPath(object, path, value) {
if (arguments.length < 2) {
throw new Error("Please provide object and path.");
}
if (typeof path !== "string") {
throw new Error("Please provide path string.");
}
var name;
var piece;
var name;
var pieceList = path.split(separator);
var last = pieceList.length - 1;
while (pieceList[last] == null || pieceList[last] === "") {
while (isNull(pieceList[last])) {
last--;
if (last < 0) {
return object;
}
}
for (var i = 0; i < last; i++) {
piece = pieceList[i];
if (piece == null || piece === "") {
if (isNull(piece)) {
continue;
}
if (name != null) {
if (name !== undefined) {
object = object[name];
}
if (piece in object) {
Expand All @@ -33,7 +76,7 @@ module.exports = function (object, path, value) {
}
throw new ReferenceError(path + " is not defined");
}
if (name != null) {
if (name !== undefined) {
object = object[name];
}
name = pieceList[last];
Expand All @@ -48,5 +91,29 @@ module.exports = function (object, path, value) {
return object[name];
}
throw new ReferenceError(path + " is not defined");
};
}


/**
* @private
* @param {*} obj
* @returns {boolean}
*/
function isNull(obj) {
if (typeof obj === "undefined") {
return true;
}
if (obj === null || obj.length === 0 || Number.isNaN(obj)) {
return true;
}
if (typeof obj === "object") {
for (var key in obj) {
if (!isNull(key)) {
return false;
}
}
return true;
}
return false;
}

68 changes: 40 additions & 28 deletions test/dotpath-tests.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";
"use strict";

var assert = require("assert");
var resolve = require("..");
var tape = require("tape");
var dotPath = require("..");

var obj = {
a: { b: 1, c: "2" },
Expand All @@ -10,28 +10,40 @@ var obj = {
f: { g: { h: [ 3, "4.5", { i: 6 } ], j: function() { return "7"; } } }
};

assert.equal(resolve(obj, ""), obj);
assert.equal(resolve(obj, "a.b"), 1);
assert.equal(resolve(obj.a, "c"), "2");
assert.equal(resolve(obj, "d"), null);
assert.equal(resolve(obj, "e"), undefined);
assert.equal(resolve(obj.f.g.h, "0"), 3);
assert.equal(resolve(obj.f.g.h, "[0]"), 3);
assert.equal(resolve(obj, "f.g.h[1]"), "4.5");
assert.equal(resolve(obj["f"], "g.h.2.i"), 6);
assert.equal(resolve(obj.f.g, "h[2].i"), 6);
assert.equal(resolve(obj.f.g, "h.[2]i"), 6);
assert.equal(resolve(obj.f.g, "h.[2].i"), 6);
assert.equal(resolve(obj.f.g, "h[2]i"), 6);
assert.equal(resolve(obj, "f.g.j")(), "7");
assert.throws(function () { resolve(); });
assert.throws(function () { resolve(obj); });
assert.throws(function () { resolve(obj, obj); });
assert.throws(function () { resolve(obj, "f.h"); });
assert.equal(resolve(obj, "k", 8), 8);
assert.equal(resolve(obj, "k"), 8);
assert.throws(function () { resolve(obj, "k.l", 9); });
assert.throws(function () { resolve(obj, "l.m", 9); });
var k = { l: 9 };
assert.equal(resolve(obj, "k", k), k);
assert.equal(resolve(obj, "k.l"), 9);
tape("get", function (assert) {
assert.equal(dotPath(obj, ""), obj);
assert.equal(dotPath(obj, "a.b"), 1);
assert.equal(dotPath(obj.a, "c"), "2");
assert.equal(dotPath(obj, "d"), null);
assert.equal(dotPath(obj, "e"), undefined);
assert.equal(dotPath(obj.f.g.h, "0"), 3);
assert.equal(dotPath(obj.f.g.h, "[0]"), 3);
assert.equal(dotPath(obj, "f.g.h[1]"), "4.5");
assert.equal(dotPath(obj["f"], "g.h.2.i"), 6);
assert.equal(dotPath(obj.f.g, "h[2].i"), 6);
assert.equal(dotPath(obj.f.g, "h.[2]i"), 6);
assert.equal(dotPath(obj.f.g, "h.[2].i"), 6);
assert.equal(dotPath(obj.f.g, "h[2]i"), 6);
assert.equal(dotPath(obj, "f.g.j")(), "7");
assert.end();
});

tape("throws", function (assert) {
assert.throws(function () { dotPath(); });
assert.throws(function () { dotPath(obj); });
assert.throws(function () { dotPath(obj, obj); });
assert.throws(function () { dotPath(obj, "f.h"); });
assert.end();
});

tape("set", function (assert) {
assert.equal(dotPath(obj, "k", 8), 8);
assert.equal(dotPath(obj, "k"), 8);
assert.throws(function () { dotPath(obj, "k.l", 9); });
assert.throws(function () { dotPath(obj, "l.m", 9); });
var k = { l: 9 };
assert.equal(dotPath(obj, "k", k), k);
assert.equal(dotPath(obj, "k.l"), 9);
assert.end();
});

0 comments on commit d695290

Please sign in to comment.