Skip to content

Commit 9fff017

Browse files
committed
feat: support * in paths
i.e. undefsafe([ { a: 1 }, { b: 2} ], '*.a') === 1
1 parent aab63c2 commit 9fff017

File tree

4 files changed

+82
-6
lines changed

4 files changed

+82
-6
lines changed

lib/undefsafe.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,40 @@ function undefsafe(obj, path, value) {
44
var parts = path.split('.');
55
var key = null;
66
var type = typeof obj;
7+
var root = obj;
78
var parent = obj;
89

10+
var star = parts.filter(function (_) { return _ === '*' }).length > 0;
11+
912
// we're dealing with a primative
1013
if (type !== 'object' && type !== 'function') {
1114
return obj;
1215
} else if (path.trim() === '') {
1316
return obj;
1417
}
1518

16-
while ((key = parts.shift())) {
19+
key = parts[0];
20+
var i = 0;
21+
for (; i < parts.length; i++) {
22+
key = parts[i];
1723
parent = obj;
24+
25+
if (key === '*') {
26+
// loop through each property
27+
var prop = '';
28+
29+
for (prop in parent) {
30+
var shallowObj = undefsafe(obj[prop], parts.slice(i + 1).join('.'), value);
31+
if (shallowObj) {
32+
if ((value && shallowObj === value) || (!value)) {
33+
return shallowObj;
34+
}
35+
}
36+
}
37+
return undefined;
38+
key = prop;
39+
}
40+
1841
obj = obj[key];
1942
if (obj === undefined || obj === null) {
2043
break;
@@ -23,13 +46,12 @@ function undefsafe(obj, path, value) {
2346

2447
// if we have a null object, make sure it's the one the user was after,
2548
// if it's not (i.e. parts has a length) then give undefined back.
26-
if (obj === null && parts.length !== 0) {
49+
if (obj === null && i !== parts.length - 1) {
2750
obj = undefined;
28-
} else if (value) {
51+
} else if (!star && value) {
2952
key = path.split('.').pop();
3053
parent[key] = value;
3154
}
32-
3355
return obj;
3456
}
3557

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
"license": "MIT",
2323
"devDependencies": {
2424
"semantic-release": "^4.3.5",
25-
"tap": "^5.7.1"
25+
"tap": "^5.7.1",
26+
"tap-only": "0.0.5"
27+
},
28+
"dependencies": {
29+
"debug": "^2.2.0"
2630
}
2731
}

test/star-rule.test.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// process.stdout.write('\033c'); // clear the screen
2+
var test = require('tap-only');
3+
var undefsafe = require('../lib/undefsafe');
4+
var fixture = {
5+
"commits": [
6+
{
7+
"modified": [
8+
"one",
9+
"two"
10+
]
11+
},
12+
{
13+
"modified": [
14+
"two",
15+
"four"
16+
]
17+
}
18+
]
19+
};
20+
21+
test('get value on first * selector', function (t) {
22+
var res = undefsafe(fixture, 'commits.*.modified.*');
23+
t.equal(res, 'one');
24+
t.end();
25+
});
26+
27+
test('walking multiple routes', function (t) {
28+
var res = undefsafe(fixture, 'commits.*.modified.*', 'four');
29+
t.equal(res, 'four');
30+
t.end();
31+
});
32+
33+
34+
test('get specific match * selector', function (t) {
35+
var res = undefsafe(fixture, 'commits.*.modified.*', 'two');
36+
t.equal(res, 'two');
37+
t.end();
38+
});
39+
40+
test('match * selector returns undefined', function (t) {
41+
var res = undefsafe(fixture, 'commits.*.modified.*', 'three');
42+
t.equal(res, undefined);
43+
t.end();
44+
});
45+
46+
test('match * selector works on objects', function (t) {
47+
var res = undefsafe(fixture, '*.*.modified.*');
48+
t.equal(res, 'one');
49+
t.end();
50+
});

test/undefsafe.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict';
2-
var test = require('tap').test;
2+
var test = require('tap-only');
33
var undefsafe = require('../lib/undefsafe');
44

55
test('should handle primatives', function (t) {

0 commit comments

Comments
 (0)