@nsilly/repository
Version:
NF Repository is a abstract layer of Sequelize Application, that make application more easy to understand and flexible to maintain.
516 lines (440 loc) • 12.9 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.QueryBuilder = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _ = _interopRequireWildcard(require("lodash"));
var _exceptions = require("@nsilly/exceptions");
var _sequelize = require("sequelize");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var QueryBuilder =
/*#__PURE__*/
function () {
function QueryBuilder() {
this.wheres = [];
this.scopeQueries = [];
this.scopes = [];
this.offset = 0;
this.limit = undefined;
this.orders = [];
this.group = undefined;
this.includes = [];
this.attributes = [];
}
var _proto = QueryBuilder.prototype;
_proto.setModels = function setModels(models) {
this.models = models;
}
/**
* Add a basic WHERE clause to the query.
*
* @param string column
* @param mixed operator
* @param mixed value
*
* @return this
*/
;
_proto.where = function where() {
var type = _sequelize.Op.and;
var column;
var operation = '=';
var value;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (args.length === 2) {
var _ref = [args[0], args[1]];
column = _ref[0];
value = _ref[1];
} else if (args.length === 3) {
column = args[0];
operation = args[1];
value = args[2];
} else if (args.length === 1) {
// means raw query
var _ref2 = [args[0], null, null];
column = _ref2[0];
operation = _ref2[1];
value = _ref2[2];
} else {
throw new _exceptions.Exception('where function expect two or three parameters', 1000);
}
this.wheres.push({
column: column,
operation: operation,
value: value,
type: type
});
return this;
}
/**
* Add a basic WHERE clause to the query.
*
* @param string column
* @param mixed operator
* @param mixed value
*
* @return this
*/
;
_proto.scopeQuery = function scopeQuery(query, type) {
if (type === void 0) {
type = _sequelize.Op.and;
}
this.scopeQueries.push({
query: query,
type: type
});
return this;
}
/**
* Add a basic OR WHERE clause to the query.
*
* @param string column
* @param mixed operator
* @param mixed value
*
* @return this
*/
;
_proto.orWhere = function orWhere() {
var type = _sequelize.Op.or;
var column;
var operation = '=';
var value;
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
if (args.length === 2) {
var _ref3 = [args[0], args[1]];
column = _ref3[0];
value = _ref3[1];
} else if (args.length === 3) {
column = args[0];
operation = args[1];
value = args[2];
} else if (args.length === 1) {
var _ref4 = [args[0], null, null];
column = _ref4[0];
operation = _ref4[1];
value = _ref4[2];
} else {
throw new _exceptions.Exception('orWhere function expect one, two or three parameters', 1000);
}
this.wheres.push({
column: column,
operation: operation,
value: value,
type: type
});
return this;
}
/**
* Add an "WHERE IN" clause to the query.
*
* @param string column
* @param array value
*
* @return this
*/
;
_proto.whereIn = function whereIn(column, value) {
var operation = _sequelize.Op["in"];
var type = _sequelize.Op.and;
this.wheres.push({
column: column,
operation: operation,
value: value,
type: type
});
return this;
}
/**
* Add an "OR WHERE IN" clause to the query.
*
* @param string column
* @param array value
*
* @return this
*/
;
_proto.orWhereIn = function orWhereIn(column, value) {
var operation = _sequelize.Op["in"];
var type = _sequelize.Op.or;
this.wheres.push({
column: column,
operation: operation,
value: value,
type: type
});
return this;
}
/**
* Add an "WHERE NOT IN" clause to the query.
*
* @param string column
* @param array value
*
* @return this
*/
;
_proto.whereNotIn = function whereNotIn(column, value) {
var operation = _sequelize.Op.notIn;
var type = _sequelize.Op.and;
this.wheres.push({
column: column,
operation: operation,
value: value,
type: type
});
return this;
}
/**
* Add a basic where clause with relation to the query.
*
* @param string relation
* @param callable callable
*
* @return this
*/
;
_proto.whereHas = function whereHas(relation, builder, options) {
options = options || {};
var model;
if (this.models !== undefined && this.models[relation] !== undefined) {
model = this.models[relation];
} else {
model = relation;
}
this.includes.push(Object.assign({
model: model,
where: builder.buildWhereQuery()
}, options));
return this;
}
/**
* include another table that has many to many relationship with it
*
* @param string relation
* @param callable builder
*
* @return this
*/
;
_proto.includeThroughWhere = function includeThroughWhere(relation, builder) {
if (this.models !== undefined && this.models[relation] !== undefined) {
this.includes.push({
model: this.models[relation],
through: {
where: builder.buildWhereQuery()
}
});
} else {
this.includes.push({
model: relation,
through: {
where: builder.buildWhereQuery()
}
});
}
return this;
}
/**
* Alias to set the "offset" value of the query.
*
* @param int value
*
* @return this
*/
;
_proto.skip = function skip(offset) {
this.offset = _.isUndefined(offset) ? 1 : parseInt(offset);
}
/**
* Alias to set the "limit" value of the query.
*
* @param int value
*
* @return this
*/
;
_proto.take = function take(limit) {
this.limit = _.isUndefined(limit) ? undefined : parseInt(limit);
}
/**
* Add an "order by" clause to the query.
*
* @param string column
* @param string direction
*
* @return this
*/
;
_proto.orderBy = function orderBy() {
var model;
var field;
var direction = 'ASC';
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
if (args.length === 2) {
field = args[0];
direction = args[1];
this.orders.push([field, direction]);
}
if (args.length === 3) {
model = args[0];
field = args[1];
direction = args[2];
this.orders.push([model, field, direction]);
}
if (args.length === 1) {
field = args[0];
this.orders.push(field);
}
}
/**
* Add an "GROUP BY" clause to the query.
*
* @param string column
*
* @return this
*/
;
_proto.groupBy = function groupBy(column) {
this.group = column;
}
/**
* Begin querying a model with eager loading.
*
* @param array|string $relations
*
* @return this
*/
;
_proto["with"] = function _with() {
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
var mainModel = args[0];
var options = args[1] || {};
if (typeof args[0] === 'string') {
if (this.models !== undefined && this.models[args[0]] !== undefined) {
mainModel = this.models[args[0]];
} else {
mainModel = args[0];
}
}
if (options.include !== undefined && typeof options.include === 'string' && this.models !== undefined && this.models[options.include] !== undefined) {
options.include = this.models[options.include];
}
var include = _objectSpread({}, options, {}, {
model: mainModel
});
this.includes.push(include);
}
/**
* Add scope to the query
*
* @param string scope
*
* @return this
*/
;
_proto.withScope = function withScope(scope) {
this.scopes.push(scope);
}
/**
* Set the columns to be selected.
*
* @param array|mixed $columns
*
* @return this
*/
;
_proto.select = function select(columns) {
this.attributes = columns;
return this;
};
_proto.resolveOperation = function resolveOperation(operation) {
switch (operation) {
case '=':
return _sequelize.Op.eq;
case '>':
return _sequelize.Op.gt;
case '<':
return _sequelize.Op.lt;
case '>=':
return _sequelize.Op.gte;
case '<=':
return _sequelize.Op.lte;
case '<>':
case '!=':
return _sequelize.Op.ne;
case 'like':
case 'LIKE':
return _sequelize.Op.like;
case 'notLike':
case 'NOTLIKE':
return _sequelize.Op.notLike;
default:
return operation;
}
};
_proto.buildWhereQuery = function buildWhereQuery() {
var _this = this;
var query = {};
var group = _.groupBy(this.wheres, 'type');
if (this.wheres.length === 0 && this.scopeQueries.length === 0) {
return query;
}
if (!_.isUndefined(group[_sequelize.Op.or]) && group[_sequelize.Op.or].length > 0) {
var _query;
query = (_query = {}, _query[_sequelize.Op.or] = [], _query);
if (!_.isUndefined(group[_sequelize.Op.and]) && group[_sequelize.Op.and].length > 0) {
var _query$Op$or$push;
var andQuery = {};
_.forEach(group[_sequelize.Op.and], function (item) {
var _andQuery$item$column;
andQuery[item.column] = (_andQuery$item$column = {}, _andQuery$item$column[_this.resolveOperation(item.operation)] = item.value, _andQuery$item$column);
});
query[_sequelize.Op.or].push((_query$Op$or$push = {}, _query$Op$or$push[_sequelize.Op.and] = andQuery, _query$Op$or$push));
}
_.forEach(group[_sequelize.Op.or], function (item) {
if (item.operation === null && item.value == null) {
query[_sequelize.Op.or].push(item.column);
} else {
var _item$column, _query$Op$or$push2;
query[_sequelize.Op.or].push((_query$Op$or$push2 = {}, _query$Op$or$push2[item.column] = (_item$column = {}, _item$column[_this.resolveOperation(item.operation)] = item.value, _item$column), _query$Op$or$push2));
}
});
} else {
var _query2;
query = (_query2 = {}, _query2[_sequelize.Op.and] = [], _query2);
_.forEach(group[_sequelize.Op.and], function (item) {
if (item.operation === null && item.value == null) {
query[_sequelize.Op.and].push(item.column);
} else {
var _item$column2, _query$Op$and$push;
query[_sequelize.Op.and].push((_query$Op$and$push = {}, _query$Op$and$push[item.column] = (_item$column2 = {}, _item$column2[_this.resolveOperation(item.operation)] = item.value, _item$column2), _query$Op$and$push));
}
});
}
if (_.isArray(this.scopeQueries) && this.scopeQueries.length > 0) {
_.forEach(this.scopeQueries, function (item) {
if (query[item.type] !== undefined && _.isArray(query[item.type])) {
var _query$item$type$push;
query[item.type].push((_query$item$type$push = {}, _query$item$type$push[item.type] = item.query.buildWhereQuery(), _query$item$type$push));
} else {
query[item.type] = item.query.buildWhereQuery();
}
});
}
return query;
};
return QueryBuilder;
}();
exports.QueryBuilder = QueryBuilder;