field-filter
Advanced tools
Comparing version 0.0.2 to 0.0.3
102
index.js
'use strict'; | ||
var _ = require('lodash'); | ||
module.exports = filter; | ||
module.exports = { | ||
filter: filter, | ||
parseFilter: parseFilter | ||
}; | ||
function filter(filterStr, source) { | ||
if (!filterStr) { | ||
return source; | ||
} | ||
if (isNaN(parseInt(filterStr[0])) && Array.isArray(source)) { | ||
return _.map(source, _.partial(filter, filterStr)); | ||
} | ||
function parseFilter(filterStr) { | ||
var openParens = 0; | ||
@@ -36,31 +31,67 @@ var keys = _.filter(_.map(_.reduce(filterStr, function (result, letter) { | ||
// fill specified keys | ||
var result = _.transform(keys, function (result, key) { | ||
var top, rest, usedKeys; | ||
return _.transform(keys, function (result, key) { | ||
var top, rest; | ||
if (/^[^(*]+\//.test(key)) { | ||
if (!_.contains(key, '(') && !_.contains(key, '/')) { | ||
result[key] = null; | ||
return; | ||
} | ||
if (/^[^(]+\//.test(key)) { | ||
top = key.slice(0, key.indexOf('/')); | ||
rest = key.slice(key.indexOf('/') + 1); | ||
result[top] = filter(rest, source[top]); | ||
result[top] = parseFilter(rest); | ||
return; | ||
} | ||
if (/^[^/*]+\(/.test(key)) { | ||
if (/^[^/]+\(/.test(key)) { | ||
top = key.slice(0, key.indexOf('(')); | ||
rest = key.slice(key.indexOf('(') + 1, key.lastIndexOf(')')); | ||
result[top] = filter(rest, source[top]); | ||
result[top] = parseFilter(rest); | ||
return; | ||
} | ||
if (/^\*/.test(key)) { | ||
if (key === '*') { | ||
result = _.defaults(result, source); | ||
return; | ||
} | ||
}, {}); | ||
} | ||
if (/^\*\//.test(key)) { | ||
usedKeys = Object.keys(result); | ||
rest = key.slice(key.indexOf('/') + 1); | ||
function filter(filterStr, source, requiredStr) { | ||
var required = parseFilter(requiredStr); | ||
if (!containsRequired(required, source)) { | ||
return null; | ||
} | ||
return _filter(parseFilter(filterStr), source); | ||
} | ||
function containsRequired(required, source) { | ||
return _.every(required, function (subRequires, require) { | ||
if (source[require] === undefined) { | ||
return false; | ||
} | ||
return containsRequired(subRequires, source[require]); | ||
}); | ||
} | ||
function _filter(fields, source) { | ||
if (!fields) { | ||
return source; | ||
} | ||
var hasNumber = _.any(Object.keys(fields), function (fieldName) { | ||
return !isNaN(parseInt(fieldName)); | ||
}); | ||
if (!hasNumber && Array.isArray(source)) { | ||
return _.map(source, _.partial(_filter, fields)); | ||
} | ||
// fill specified keys | ||
var result = _.transform(fields, function (result, subFields, field) { | ||
if (field === '*') { | ||
if (subFields) { | ||
var usedKeys = Object.keys(result); | ||
_.forEach(_.keys(source), function (top) { | ||
if (!_.contains(usedKeys, top)) { | ||
result[top] = filter(rest, source[top]); | ||
result[top] = _filter(subFields, source[top]); | ||
} | ||
@@ -71,16 +102,13 @@ }); | ||
if (/^\*\(/.test(key)) { | ||
usedKeys = Object.keys(result); | ||
rest = key.slice(key.indexOf('(') + 1, key.lastIndexOf(')')); | ||
_.forEach(_.keys(source), function (top) { | ||
if (!_.contains(usedKeys, top)) { | ||
result[top] = filter(rest, source[top]); | ||
} | ||
}); | ||
return; | ||
} | ||
result = _.defaults(result, source); | ||
return; | ||
} | ||
result[key] = source[key]; | ||
if (source[field] === undefined) { | ||
return; | ||
} | ||
result[field] = _filter(subFields, source[field]); | ||
return; | ||
}, Array.isArray(source) ? [] : {}); | ||
@@ -87,0 +115,0 @@ |
{ | ||
"name": "field-filter", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "api query parameter result object filter", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
82
test.js
'use strict'; | ||
var filter = require('./index'); | ||
var filter = require('./index').filter; | ||
var parseFilter = require('./index').parseFilter; | ||
var chai = require('chai'); | ||
var expect = chai.expect; | ||
describe('parseFilter', function () { | ||
it('generates a filter object', function () { | ||
var input = 'a,b/c,d(e,f),g/*/h,i/*(j,k/l)'; | ||
expect(parseFilter(input)).to.deep.equal({ | ||
a: null, | ||
b: { | ||
c: null | ||
}, | ||
d: { | ||
e: null, | ||
f: null | ||
}, | ||
g: { | ||
'*': { | ||
h: null | ||
} | ||
}, | ||
i: { | ||
'*': { | ||
j: null, | ||
k: { | ||
l: null | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
}); | ||
describe('Filter', function () { | ||
@@ -259,2 +289,52 @@ it('basic keys', function () { | ||
}); | ||
it('ignores fields that dont exist', function () { | ||
var input = { | ||
a: { | ||
b: 'b' | ||
} | ||
}; | ||
var filterString = 'a/c/d'; | ||
expect(filter(filterString, input)).to.deep.equal({ | ||
a: {} | ||
}); | ||
}); | ||
}); | ||
describe('Required', function () { | ||
it('requires', function () { | ||
var input = { | ||
a: 'a' | ||
}; | ||
var requireString = 'b/c'; | ||
expect(filter('*', input, requireString)).to.equal(null); | ||
}); | ||
it('passes required', function () { | ||
var input = { | ||
a: { | ||
b: { | ||
c: 'c' | ||
}, | ||
d: 'd' | ||
}, | ||
e: 'e' | ||
}; | ||
var requireString = 'a(b/c,d)'; | ||
expect(filter('*', input, requireString)).to.deep.equal({ | ||
a: { | ||
b: { | ||
c: 'c' | ||
}, | ||
d: 'd' | ||
}, | ||
e: 'e' | ||
}); | ||
}); | ||
}); |
11734
399