@reflaunt/nsilly-sequelize
Version:
Reflaunt Nsilly sequelize is a abstract layer of Sequelize Application, that make application more easy to understand and flexible to maintain.
585 lines (497 loc) • 13.4 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
exports.__esModule = true;
exports.QueryBuilder = void 0;
var _ = _interopRequireWildcard(require("lodash"));
var _exceptions = require("@nsilly/exceptions");
var _sequelize = require("sequelize");
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() {
var _this = this;
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
if (_.isArray(args[0])) {
args = args[0];
}
var mainModel = args[0];
if (typeof args[0] === 'string') {
if (this.models !== undefined && this.models[args[0]] !== undefined) {
mainModel = this.models[args[0]];
} else {
mainModel = args[0];
}
}
var include = {
model: mainModel
};
var arr = [];
var arrayInclude = [];
var obj = {};
for (var i = 1; i < args.length; i++) {
if (args[i]) {
arr.push(args[i].split(':'));
}
}
_.forEach(arr, function (item) {
switch (item[0]) {
case 'as':
obj[item[0]] = item[1];
Object.assign(include, obj);
break;
case 'attributes':
obj[item[0]] = [];
for (var j = 1; j < item.length; j++) {
obj[item[0]].push(item[j]);
}
Object.assign(include, obj);
break;
case 'include':
var model = item[1];
if (typeof item[1] === 'string') {
if (_this.models !== undefined && _this.models[item[1]] !== undefined) {
model = _this.models[item[1]];
} else {
model = item[1];
}
}
var includeObj = {
model: model
};
if (item[2] === 'as') {
Object.assign(includeObj, {
as: item[3]
});
}
arrayInclude.push(includeObj);
break;
default:
break;
}
});
arrayInclude = _.reverse(arrayInclude);
for (var _i = 0; _i < arrayInclude.length - 1; _i++) {
Object.assign(arrayInclude[_i + 1], {
include: arrayInclude[_i]
});
}
if (!_.isNil(arrayInclude[arrayInclude.length - 1])) {
Object.assign(include, {
include: arrayInclude[arrayInclude.length - 1]
});
}
_.forEach(this.includes, function (value) {
if (value['model'] === include['model'] && include['include']) {
Object.assign(value, include);
include = {};
}
});
if (!_.isEmpty(include)) {
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 _this2 = 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[_this2.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[_this2.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[_this2.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;