blow-query
Version:
Programmatically build queries which can be returned as JSON Object and used to fetch data from many sources.
166 lines (165 loc) • 4.86 kB
JavaScript
'use strict';
var util_1 = require('util');
class Query {
constructor(query) {
if (!util_1.isUndefined(query)) {
if (query instanceof Query) {
query = query.toJSON();
}
}
const q = (query || {});
this._where = q.where || {};
this._limit = q.limit || -1;
this._skip = q.skip || 0;
this._sort = q.sort || {};
this._select = q.select || [];
}
_addCondition(field, condition, value) {
if (util_1.isUndefined(this._where[field]) || util_1.isString(this._where[field])) {
this._where[field] = {};
}
this._where[field][condition] = value;
return this;
}
_sortItem(field, direction) {
const item = {};
item[field] = direction;
return item;
}
equal(field, value) {
this._where[field] = value;
return this;
}
notEqual(field, value) {
return this._addCondition(field, '$neq', value);
}
lessThan(field, value) {
return this._addCondition(field, '$lt', value);
}
lessThanOrEqual(field, value) {
return this._addCondition(field, '$lte', value);
}
greaterThan(field, value) {
return this._addCondition(field, '$gt', value);
}
greaterThanOrEqual(field, value) {
return this._addCondition(field, '$gte', value);
}
containedIn(field, values) {
return this._addCondition(field, '$in', values);
}
notContainedIn(field, values) {
return this._addCondition(field, '$nin', values);
}
regex(field, value) {
return this._addCondition(field, '$regex', value);
}
contains(field, value) {
return this._addCondition(field, '$regex', value);
}
startsWith(field, value) {
return this._addCondition(field, '$regex', `^${value}`);
}
endsWith(field, value) {
return this._addCondition(field, '$regex', `${value}$`);
}
ascending(field) {
Object.assign(this._sort, this._sortItem(field, 1));
return this;
}
descending(field) {
Object.assign(this._sort, this._sortItem(field, -1));
return this;
}
skip(skip) {
this._skip = skip;
return this;
}
limit(limit) {
this._limit = limit;
return this;
}
select(fields) {
if (!util_1.isArray(fields)) {
fields = [fields];
}
this._select = this._select.concat(fields || []);
return this;
}
or(query) {
this._where = { $or: [this._where, query.toJSON().where] };
return this;
}
toJSON() {
const query = {};
if (Object.keys(this._where).length) {
query.where = this._where;
}
if (this._skip) {
query.skip = this._skip;
}
if (this._limit > 0) {
query.limit = this._limit;
}
if (this._select.length > 0) {
query.select = this._select;
}
if (Object.keys(this._sort).length) {
query.sort = this._sort;
}
return Object.assign({}, query);
}
static create() {
return new Query();
}
static from(input) {
const query = { where: {} };
if (util_1.isString(input)) {
try {
input = JSON.parse(input);
}
catch (e) {
throw new Error('Invalid input data for query.');
}
}
if (util_1.isObject(input)) {
if (input.where) {
try {
input.where = JSON.parse(input.where);
}
catch (e) {
throw new Error('Invalid input data for query(where).');
}
if (util_1.isObject(input.where)) {
query.where = input.where;
}
}
if (input.limit) {
query.limit = parseInt(input.limit);
}
if (input.skip) {
query.skip = parseInt(input.skip);
}
if (input.sort) {
try {
input.sort = JSON.parse(input.sort);
}
catch (e) {
throw new Error('Invalid input data for query(sort).');
}
if (util_1.isObject(input.sort)) {
query.sort = {};
query.sort = Object.keys(input.sort).reduce((s, c) => {
s[c] = parseInt(input.sort[c]);
return s;
}, query.sort);
}
}
if (input.select) {
query.select = input.select;
}
}
return new Query(query);
}
}
exports.Query = Query;