Skip to content

Commit

Permalink
feat: support * in paths
Browse files Browse the repository at this point in the history
i.e. undefsafe([ { a: 1 }, { b: 2} ], '*.a') === 1
  • Loading branch information
remy committed Aug 23, 2016
1 parent aab63c2 commit 9fff017
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 6 deletions.
30 changes: 26 additions & 4 deletions lib/undefsafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,40 @@ function undefsafe(obj, path, value) {
var parts = path.split('.');
var key = null;
var type = typeof obj;
var root = obj;
var parent = obj;

var star = parts.filter(function (_) { return _ === '*' }).length > 0;

// we're dealing with a primative
if (type !== 'object' && type !== 'function') {
return obj;
} else if (path.trim() === '') {
return obj;
}

while ((key = parts.shift())) {
key = parts[0];
var i = 0;
for (; i < parts.length; i++) {
key = parts[i];
parent = obj;

if (key === '*') {
// loop through each property
var prop = '';

for (prop in parent) {
var shallowObj = undefsafe(obj[prop], parts.slice(i + 1).join('.'), value);
if (shallowObj) {
if ((value && shallowObj === value) || (!value)) {
return shallowObj;
}
}
}
return undefined;
key = prop;
}

obj = obj[key];
if (obj === undefined || obj === null) {
break;
Expand All @@ -23,13 +46,12 @@ function undefsafe(obj, path, value) {

// if we have a null object, make sure it's the one the user was after,
// if it's not (i.e. parts has a length) then give undefined back.
if (obj === null && parts.length !== 0) {
if (obj === null && i !== parts.length - 1) {
obj = undefined;
} else if (value) {
} else if (!star && value) {
key = path.split('.').pop();
parent[key] = value;
}

return obj;
}

Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
"license": "MIT",
"devDependencies": {
"semantic-release": "^4.3.5",
"tap": "^5.7.1"
"tap": "^5.7.1",
"tap-only": "0.0.5"
},
"dependencies": {
"debug": "^2.2.0"
}
}
50 changes: 50 additions & 0 deletions test/star-rule.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// process.stdout.write('\033c'); // clear the screen
var test = require('tap-only');
var undefsafe = require('../lib/undefsafe');
var fixture = {
"commits": [
{
"modified": [
"one",
"two"
]
},
{
"modified": [
"two",
"four"
]
}
]
};

test('get value on first * selector', function (t) {
var res = undefsafe(fixture, 'commits.*.modified.*');
t.equal(res, 'one');
t.end();
});

test('walking multiple routes', function (t) {
var res = undefsafe(fixture, 'commits.*.modified.*', 'four');
t.equal(res, 'four');
t.end();
});


test('get specific match * selector', function (t) {
var res = undefsafe(fixture, 'commits.*.modified.*', 'two');
t.equal(res, 'two');
t.end();
});

test('match * selector returns undefined', function (t) {
var res = undefsafe(fixture, 'commits.*.modified.*', 'three');
t.equal(res, undefined);
t.end();
});

test('match * selector works on objects', function (t) {
var res = undefsafe(fixture, '*.*.modified.*');
t.equal(res, 'one');
t.end();
});
2 changes: 1 addition & 1 deletion test/undefsafe.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
var test = require('tap').test;
var test = require('tap-only');
var undefsafe = require('../lib/undefsafe');

test('should handle primatives', function (t) {
Expand Down

0 comments on commit 9fff017

Please sign in to comment.