Skip to content

Commit

Permalink
Merge pull request #11 from Turistforeningen/feat/boolean-strings
Browse files Browse the repository at this point in the history
Parse Boolean Strings
  • Loading branch information
Starefossen committed Feb 10, 2016
2 parents c32f938 + 6330344 commit 873e92a
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 21 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ useful when building an API and accepting various user specificed queries.
* `$nin`
* `$exists`
* `$regex`
* Parse string integers and floats to numbers
* Parse string boolean to ture/false booleans

| operation | query string | query object |
|-----------|---------------|--------------|
Expand Down Expand Up @@ -69,11 +71,16 @@ var MongoQS = require('mongo-querystring');

### new MongoQS(`object` options)

* `Array` ops - list of supported operators
* `object` alias - query param aliases
* `object` blacklist - blacklisted query params
* `object` whitelist - whitelisted query params
* `object` custom - custom query params
* `Array` ops - list of supported operators (default: `['!', '^', '$', '~', '>', '<', '$in']`)
* `object` alias - query param aliases (default: `{}`)
* `object` blacklist - blacklisted query params (default: `{}`)
* `object` whitelist - whitelisted query params (default: `{}`)
* `object` custom - custom query params (default: `{}`)
* `object` string - string parsing
* `boolean` toBoolean - parse `"true"`, `"false"` string to booleans (default: `true`)
* `boolean` toNumber - parse string integer and float values to numbers (default: `true`)
* `regexp` keyRegex - allowed key names (default: `/^[a-zæøå0-9-_.]+$/i`)
* `regexp` arrRegex - allowed array key names (default: `/^[a-zæøå0-9-_.]+(\[\])?$/i`)

#### Bult in custom queries

Expand Down
33 changes: 25 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ module.exports = function MongoQS(opts) {
this.whitelist = opts.whitelist || {};
this.custom = opts.custom || {};

// String Value Parsing
opts.string = opts.string || {};
this.string = opts.string || {};
this.string.toBoolean = opts.string.toBoolean || true;
this.string.toNumber = opts.string.toNumber || true;

this.keyRegex = opts.keyRegex || /^[a-zæøå0-9-_.]+$/i;
this.arrRegex = opts.arrRegex || /^[a-zæøå0-9-_.]+(\[\])?$/i;

Expand Down Expand Up @@ -100,6 +106,18 @@ module.exports.prototype.customAfter = function(field) {
};
};

module.exports.prototype.parseString = function(string) {
if (this.string.toBoolean && string.toLowerCase() === 'true') {
return true;
} else if (this.string.toBoolean && string.toLowerCase() === 'false') {
return false;
} else if (this.string.toNumber && !isNaN(string)) {
return parseFloat(string, 10);
} else {
return string;
}
};

module.exports.prototype.parse = function(query) {
var op, val;
var res = {};
Expand Down Expand Up @@ -138,17 +156,16 @@ module.exports.prototype.parse = function(query) {
res[key] = {$in: val.filter(function(element) {
return element[0] !== '!';
}).map(function(element) {
return isNaN(element) ? element : parseFloat(element, 10);
})};
return this.parseString(element);
}.bind(this))};

// $nin query
} else {
res[key] = {$nin: val.filter(function(element) {
return element[0] === '!';
}).map(function(element) {
element = element.substr(1);
return isNaN(element) ? element : parseFloat(element, 10);
})};
return this.parseString(element.substr(1));
}.bind(this))};
}
}

Expand All @@ -173,7 +190,7 @@ module.exports.prototype.parse = function(query) {
switch (op) {
case '!':
if (val) {
return { $ne: isNaN(val) ? val : parseFloat(val, 10) };
return { $ne: this.parseString(val) };
} else {
return { $exists: false };
}
Expand All @@ -193,9 +210,9 @@ module.exports.prototype.parse = function(query) {
return { $regex: val, $options: 'i' };
}
}
})();
}.bind(this))();
} else {
res[key] = isNaN(val) ? val : parseFloat(val, 10);
res[key] = this.parseString(val);
}
}
return res;
Expand Down
79 changes: 71 additions & 8 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,47 @@ describe('customAfter()', function() {
});
});

describe('parseString()', function() {
it('returns boolean true for "true" string', function() {
assert.equal(qs.parseString('true'), true);
});

it('returns string "true" when boolean parsing is disabled', function() {
qs.string.toBoolean = false;
assert.equal(qs.parseString('true'), 'true');
});

it('returns boolean false for "flase" string', function() {
assert.equal(qs.parseString('false'), false);
});

it('returns string "false" when boolean parsing is disabled', function() {
qs.string.toBoolean = false;
assert.equal(qs.parseString('false'), 'false');
});

it('returns number for parseable integer', function() {
assert.equal(qs.parseString('100'), 100);
});

it('returns string number when number parsing is disabled', function() {
qs.string.toNumber = false;
assert.equal(qs.parseString('100'), '100');
});

it('returns number for zero padded parseable integer', function() {
assert.equal(qs.parseString('000100'), 100);
});

it('returns number for parseable float', function() {
assert.equal(qs.parseString('10.123'), 10.123);
});

it('returns number for zero padded parseable float', function() {
assert.equal(qs.parseString('00010.123'), 10.123);
});
});

describe('parse()', function() {
describe('parsing', function() {
describe('key value validation', function() {
Expand Down Expand Up @@ -143,6 +184,17 @@ describe('parse()', function() {
});
});

it('return string boolean as boolean', function() {
query = qs.parse({
foo: 'true',
bar: 'false'
});
assert.deepEqual(query, {
foo: true,
bar: false
});
});

it('returns string integer as number', function() {
query = qs.parse({
navn: '10'
Expand Down Expand Up @@ -185,6 +237,17 @@ describe('parse()', function() {
});
});

it('return string boolean as boolean', function() {
query = qs.parse({
foo: '!true',
bar: '!false'
});
assert.deepEqual(query, {
foo: {$ne: true},
bar: {$ne: false}
});
});

it('returns string integer as number', function() {
query = qs.parse({
navn: '!10'
Expand Down Expand Up @@ -289,23 +352,23 @@ describe('parse()', function() {

describe('$in / $nin operator', function() {
it('returns in array query', function() {
var string = 'foo[]=10&foo[]=10.011&foo[]=bar';
var string = 'foo[]=10&foo[]=10.011&foo[]=bar&foo[]=true';
var params = require('querystring').parse(string);

assert.deepEqual(qs.parse(params), {
foo: {
$in: [10, 10.011, 'bar']
$in: [10, 10.011, 'bar', true]
}
});
});

it('returns in array query with "qs" parser (GH-06)', function() {
var string = 'foo[]=10&foo[]=10.011&foo[]=bar';
var string = 'foo[]=10&foo[]=10.011&foo[]=bar&foo[]=true';
var params = require('qs').parse(string);

assert.deepEqual(qs.parse(params), {
foo: {
$in: [10, 10.011, 'bar']
$in: [10, 10.011, 'bar', true]
}
});
});
Expand All @@ -322,23 +385,23 @@ describe('parse()', function() {
});

it('returns not in array query', function() {
var string = 'foo[]=!10&foo[]=!10.011&foo[]=!bar';
var string = 'foo[]=!10&foo[]=!10.011&foo[]=!bar&foo[]=!false';
var params = require('querystring').parse(string);

assert.deepEqual(qs.parse(params), {
foo: {
$nin: [10, 10.011, 'bar']
$nin: [10, 10.011, 'bar', false]
}
});
});

it('returns not in array query with "gs" parser (GH-06)', function() {
var string = 'foo[]=!10&foo[]=!10.011&foo[]=!bar';
var string = 'foo[]=!10&foo[]=!10.011&foo[]=!bar&foo[]=!false';
var params = require('qs').parse(string);

assert.deepEqual(qs.parse(params), {
foo: {
$nin: [10, 10.011, 'bar']
$nin: [10, 10.011, 'bar', false]
}
});
});
Expand Down

0 comments on commit 873e92a

Please sign in to comment.