Comparing version 0.0.1 to 1.0.0
(function() { | ||
var Qs2Mongo, _, | ||
var Qs2Mongo, TypeCaster, _, schemas, | ||
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, | ||
@@ -8,3 +8,30 @@ slice = [].slice; | ||
TypeCaster = require("./typeCaster"); | ||
schemas = require("./schemas"); | ||
module.exports = Qs2Mongo = (function() { | ||
Qs2Mongo.Schemas = schemas; | ||
Qs2Mongo.MongooseSchema = function(schema, options) { | ||
if (options == null) { | ||
options = {}; | ||
} | ||
return new this(_.merge({ | ||
schema: new schemas.Mongoose(schema) | ||
}, options)); | ||
}; | ||
Qs2Mongo.ManualSchema = function(fields, options) { | ||
if (fields == null) { | ||
fields = {}; | ||
} | ||
if (options == null) { | ||
options = {}; | ||
} | ||
return new this(_.merge({ | ||
schema: new schemas.Manual(fields) | ||
}, options)); | ||
}; | ||
Qs2Mongo.defaultOmitableProperties = ['by', 'ids', 'attributes', 'offset', 'limit', 'sort']; | ||
@@ -15,15 +42,14 @@ | ||
function Qs2Mongo(arg) { | ||
var ref, ref1, ref2, ref3, ref4; | ||
this.defaultSort = arg.defaultSort, this.idField = (ref = arg.idField) != null ? ref : "id", this.multigetIdField = (ref1 = arg.multigetIdField) != null ? ref1 : "_id", this.filterableBooleans = (ref2 = arg.filterableBooleans) != null ? ref2 : [], this.filterableDates = (ref3 = arg.filterableDates) != null ? ref3 : [], this.omitableProperties = (ref4 = arg.omitableProperties) != null ? ref4 : Qs2Mongo.defaultOmitableProperties; | ||
var ref, ref1, ref2; | ||
this.schema = arg.schema, this.defaultSort = arg.defaultSort, this.idField = (ref = arg.idField) != null ? ref : "id", this.multigetIdField = (ref1 = arg.multigetIdField) != null ? ref1 : "_id", this.omitableProperties = (ref2 = arg.omitableProperties) != null ? ref2 : Qs2Mongo.defaultOmitableProperties; | ||
this.buildIdFilters = bind(this.buildIdFilters, this); | ||
this._transformFilters = bind(this._transformFilters, this); | ||
this._castFilters = bind(this._castFilters, this); | ||
this._castByName = bind(this._castByName, this); | ||
this.buildSort = bind(this.buildSort, this); | ||
this._mergeWithOperators = bind(this._mergeWithOperators, this); | ||
this.castDateFilters = bind(this.castDateFilters, this); | ||
this.castBooleanFilters = bind(this.castBooleanFilters, this); | ||
this.buildFilters = bind(this.buildFilters, this); | ||
this.buildSort = bind(this.buildSort, this); | ||
this._omitableProperties = bind(this._omitableProperties, this); | ||
this.buildSearch = bind(this.buildSearch, this); | ||
this.buildFilters = bind(this.buildFilters, this); | ||
this._makeOrFilters = bind(this._makeOrFilters, this); | ||
this._parseOperator = bind(this._parseOperator, this); | ||
this._castOrOperands = bind(this._castOrOperands, this); | ||
this._parseOperators = bind(this._parseOperators, this); | ||
@@ -33,2 +59,9 @@ this._getFilters_ = bind(this._getFilters_, this); | ||
this.parse = bind(this.parse, this); | ||
this.typeCaster = new TypeCaster({ | ||
booleans: this.schema.booleans(), | ||
dates: this.schema.dates(), | ||
numbers: this.schema.numbers(), | ||
objectIds: this.schema.objectIds(), | ||
omitableProperties: this.omitableProperties | ||
}); | ||
} | ||
@@ -85,3 +118,3 @@ | ||
return function(value, field) { | ||
var name, obj, obj1, obj2, operator; | ||
var name, obj, operator; | ||
operator = _.find(Qs2Mongo.operators, function(operator) { | ||
@@ -98,11 +131,3 @@ return _.endsWith(field, "__" + operator); | ||
name = field.replace("__" + operator, ""); | ||
return ( | ||
obj1 = {}, | ||
obj1["" + name] = ( | ||
obj2 = {}, | ||
obj2["$" + operator] = value.source || value, | ||
obj2 | ||
), | ||
obj1 | ||
); | ||
return _this._parseOperator(name, operator, value); | ||
}; | ||
@@ -116,23 +141,66 @@ })(this)); | ||
})(this)); | ||
return rv; | ||
return this._castOrOperands(rv); | ||
}; | ||
Qs2Mongo.prototype._castOrOperands = function(filters) { | ||
if (filters["$or"]) { | ||
filters["$or"] = _.compact(filters["$or"].map((function(_this) { | ||
return function(filter) { | ||
var name, obj, value; | ||
name = _.head(_.keys(filter)); | ||
value = _this._castByName(name, filter[name]); | ||
if (!_.isUndefined(value)) { | ||
return ( | ||
obj = {}, | ||
obj["" + name] = value, | ||
obj | ||
); | ||
} | ||
}; | ||
})(this))); | ||
} | ||
return filters; | ||
}; | ||
Qs2Mongo.prototype._parseOperator = function(name, operator, operand) { | ||
var argument, obj, obj1; | ||
argument = operand.source || operand; | ||
if ((operator === "in" || operator === "nin") && _.isString(argument)) { | ||
argument = argument.split(',').map((function(_this) { | ||
return function(it) { | ||
return _this._castByName(name, it); | ||
}; | ||
})(this)); | ||
} | ||
return ( | ||
obj = {}, | ||
obj["" + name] = ( | ||
obj1 = {}, | ||
obj1["$" + operator] = argument, | ||
obj1 | ||
), | ||
obj | ||
); | ||
}; | ||
Qs2Mongo.prototype._makeOrFilters = function(filters) { | ||
var _toCondition; | ||
_toCondition = _.curry(function(value, fieldNames) { | ||
var fields, obj; | ||
fields = fieldNames.split(','); | ||
switch (fields.length) { | ||
case 1: | ||
return ( | ||
obj = {}, | ||
obj["" + fields[0]] = value, | ||
obj | ||
); | ||
default: | ||
return { | ||
"$or": fields.map(_toCondition(value)) | ||
}; | ||
} | ||
}); | ||
_toCondition = _.curry((function(_this) { | ||
return function(value, fieldNames) { | ||
var fields, obj; | ||
fields = fieldNames.split(','); | ||
switch (fields.length) { | ||
case 1: | ||
return ( | ||
obj = {}, | ||
obj["" + fields[0]] = value, | ||
obj | ||
); | ||
default: | ||
return { | ||
"$or": fields.map(_toCondition(value)) | ||
}; | ||
} | ||
}; | ||
})(this)); | ||
return _.merge.apply(_, [{}].concat(slice.call(_.map(filters, _toCondition)))); | ||
@@ -147,4 +215,3 @@ }; | ||
idFilters = this.buildIdFilters(filters.ids); | ||
this.castBooleanFilters(filters); | ||
this.castDateFilters(filters); | ||
this._castFilters(filters); | ||
return _(filters).omit(propertiesToOmit).merge(idFilters).value(); | ||
@@ -161,20 +228,28 @@ }; | ||
Qs2Mongo.prototype.stringToBoolean = function(value, _default) { | ||
var ref; | ||
return ((ref = value != null ? typeof value.toLowerCase === "function" ? value.toLowerCase() : void 0 : void 0) != null ? ref : _default != null ? _default.toString() : void 0) === 'true'; | ||
}; | ||
Qs2Mongo.prototype.buildSearch = function(arg) { | ||
var booleans, dates, filterableDates, idFilters, query, search; | ||
var casteableFields, castedFilters, filters, idFilters, query, search; | ||
query = arg.query; | ||
filterableDates = this._mergeWithOperators(this.filterableDates); | ||
search = _.omit(query, this.filterableBooleans.concat(this.omitableProperties).concat(filterableDates)); | ||
booleans = _.pick(query, this.filterableBooleans); | ||
dates = _.pick(query, filterableDates); | ||
this.castBooleanFilters(booleans); | ||
this.castDateFilters(dates); | ||
idFilters = this.buildIdFilters(query.ids); | ||
return _.merge(dates, booleans, idFilters, this._asLikeIgnoreCase(search)); | ||
filters = _.clone(query); | ||
casteableFields = _.flatMap(["dates", "numbers", "objectIds", "booleans"], (function(_this) { | ||
return function(getter) { | ||
return _this._mergeWithOperators(_this.schema[getter]()); | ||
}; | ||
})(this)); | ||
search = _.omit(filters, casteableFields, this.omitableProperties); | ||
this._castFilters(filters); | ||
castedFilters = _.pick(filters, casteableFields); | ||
idFilters = this.buildIdFilters(filters.ids); | ||
return _.merge(castedFilters, idFilters, this._asLikeIgnoreCase(search)); | ||
}; | ||
Qs2Mongo.prototype._mergeWithOperators = function(fields) { | ||
return _.flatMap(fields, (function(_this) { | ||
return function(field) { | ||
return Qs2Mongo.operators.map(function(it) { | ||
return field + "__" + it; | ||
}).concat(field); | ||
}; | ||
})(this)); | ||
}; | ||
Qs2Mongo.prototype._asLikeIgnoreCase = function(search) { | ||
@@ -187,6 +262,2 @@ return _.reduce(search, (function(result, value, field) { | ||
Qs2Mongo.prototype._omitableProperties = function() { | ||
return ['by', 'ids', 'attributes', 'offset', 'limit', 'sort']; | ||
}; | ||
Qs2Mongo.prototype.buildSort = function(field) { | ||
@@ -210,45 +281,15 @@ var descending, obj; | ||
Qs2Mongo.prototype.buildFilters = function(arg) { | ||
var filters, idFilters, propertiesToOmit, query; | ||
query = arg.query; | ||
filters = _.clone(query); | ||
propertiesToOmit = this.omitableProperties; | ||
idFilters = this.buildIdFilters(filters.ids); | ||
this.castBooleanFilters(filters); | ||
this.castDateFilters(filters); | ||
return _(filters).omit(propertiesToOmit).merge(idFilters).value(); | ||
Qs2Mongo.prototype._castByName = function(name, value) { | ||
var obj; | ||
return this._castFilters(( | ||
obj = {}, | ||
obj["" + name] = value, | ||
obj | ||
))[name]; | ||
}; | ||
Qs2Mongo.prototype.castBooleanFilters = function(query) { | ||
return this._transformFilters(query, this.filterableBooleans, this.stringToBoolean); | ||
Qs2Mongo.prototype._castFilters = function(filters) { | ||
return this.typeCaster.castFilters(filters); | ||
}; | ||
Qs2Mongo.prototype.castDateFilters = function(query) { | ||
return this._transformFilters(query, this.filterableDates, function(it) { | ||
return new Date(it.source || it); | ||
}); | ||
}; | ||
Qs2Mongo.prototype._mergeWithOperators = function(fields) { | ||
return _.flatMap(fields, (function(_this) { | ||
return function(field) { | ||
return Qs2Mongo.operators.map(function(it) { | ||
return field + "__" + it; | ||
}).concat(field); | ||
}; | ||
})(this)); | ||
}; | ||
Qs2Mongo.prototype._transformFilters = function(query, fields, transformation) { | ||
var filtersWithOperators; | ||
filtersWithOperators = this._mergeWithOperators(fields); | ||
return filtersWithOperators.forEach((function(_this) { | ||
return function(field) { | ||
if (query[field] != null) { | ||
return query[field] = transformation(query[field]); | ||
} | ||
}; | ||
})(this)); | ||
}; | ||
Qs2Mongo.prototype.buildIdFilters = function(ids) { | ||
@@ -255,0 +296,0 @@ if (ids != null) { |
{ | ||
"name": "qs2mongo", | ||
"version": "0.0.1", | ||
"version": "1.0.0", | ||
"description": "qs2mongo", | ||
@@ -17,4 +17,5 @@ "main": "index.js", | ||
"coffee-script": "1.11.0", | ||
"lodash": "4.15.0", | ||
"mocha": "^3.2.0" | ||
"lodash": "4.17.4", | ||
"mocha": "3.2.0", | ||
"mongodb": "^2.2.27" | ||
}, | ||
@@ -27,2 +28,3 @@ "devDependencies": { | ||
"grunt-mocha-test": "0.13.2", | ||
"mongoose": "4.10.4", | ||
"should": "11.1.0" | ||
@@ -29,0 +31,0 @@ }, |
@@ -17,4 +17,5 @@ # qs2mongo | ||
- not strict: `key=value` is `{ key: /value/gi }` | ||
- or: `key,anotherKey=value` is `$or: [{key:value}, {anotherKey:anotherValue}]` | ||
- unary operators: `key__gt=value` is `{key: $gt: "value"}` | ||
- $or: `key,anotherKey=value` is `$or: [{key:value}, {anotherKey:value}]` | ||
- $in : `key__in=a,b,c` is `key: $in: ["a","b","c"]` | ||
- unary operators: `key__gt=value` is `{key: { $gt: "value"} }` | ||
@@ -25,3 +26,17 @@ #### Basic usage | ||
Qs2Mongo = require ("qs2mongo") | ||
qs2mongo = new Qs2Mongo() | ||
#Bind types to mongoose schema | ||
qs2mongo = Qs2Mongo.MongooseSchema YourMongooseSchema, {...otherOptions...} | ||
#Or manually specify types | ||
qs2mongo = Qs2Mongo.ManualSchema { | ||
filterableBooleans, | ||
filterableNumbers, | ||
filterableDates, | ||
filterableObjectIds | ||
}, {...otherOptions...} | ||
``` | ||
``` Coffeescript | ||
#... | ||
@@ -54,4 +69,2 @@ anEndpoint: (req, res): => | ||
multigetIdField = "_id", | ||
filterableBooleans = [], | ||
filterableDates = [], | ||
omitableProperties = Qs2Mongo.defaultOmitableProperties | ||
@@ -62,8 +75,19 @@ } | ||
#### Specify types of querystring keys | ||
## Advanced | ||
``` Coffeescript | ||
qs2mongo = new Qs2Mongo | ||
filterableBooleans: ["aBooleanField","anotherBooleanField"] | ||
filterableDates: ["aDateField","anotherDateField"] | ||
Default driver is mongodb. If you'd like to use a custom mongodb driver, you must provide your own type conversion implementation as follows: | ||
``` Coffesscript | ||
{ | ||
toObjectId: (it) -> #your conversion | ||
toNumber: (it) -> #your conversion | ||
toBoolean: (it) -> #your conversion | ||
toDate: (it) -> #your conversion | ||
} | ||
``` | ||
Note: Your conversion must return the properly converted value if `it` is valid or `undefined` otherwise. | ||
Specify the path to your implementation in process.env.QS_TRANSFORMER_DRIVER |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
61356
15
478
0
89
5
7
2
1
+ Addedmongodb@^2.2.27
+ Addedbson@1.0.9(transitive)
+ Addedbuffer-shims@1.0.0(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addeddebug@2.2.0(transitive)
+ Addeddiff@1.4.0(transitive)
+ Addedes6-promise@3.2.1(transitive)
+ Addedglob@7.0.5(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedlodash@4.17.4(transitive)
+ Addedmocha@3.2.0(transitive)
+ Addedmongodb@2.2.36(transitive)
+ Addedmongodb-core@2.1.20(transitive)
+ Addedms@0.7.1(transitive)
+ Addedprocess-nextick-args@1.0.7(transitive)
+ Addedreadable-stream@2.2.7(transitive)
+ Addedrequire_optional@1.0.1(transitive)
+ Addedresolve-from@2.0.0(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedsemver@5.7.2(transitive)
+ Addedstring_decoder@1.0.3(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
- Removeddebug@2.6.8(transitive)
- Removeddiff@3.2.0(transitive)
- Removedglob@7.1.1(transitive)
- Removedhe@1.1.1(transitive)
- Removedlodash@4.15.0(transitive)
- Removedmocha@3.5.3(transitive)
- Removedms@2.0.0(transitive)
Updatedlodash@4.17.4
Updatedmocha@3.2.0