total5
Version:
Total.js framework v5
1,243 lines (999 loc) • 27.3 kB
JavaScript
// Total.js QueryBuilder
// The MIT License
// Copyright 2023 (c) Peter Širka <petersirka@gmail.com>
const REG_FIELDS_CLEANER = /"|`|\||'|\s/g;
var LANGUAGE_SKIP = '_';
var LANGUAGE_PREFIX = '';
function QueryBuilderOptions() {}
function Controller(singleton) {
var t = this;
if (!singleton) {
t.commands = [];
t.response = {};
t.error = null;
setImmediate(t.next, t);
}
}
function DB(conn) {
var t = this;
t.conn = conn;
t.options = new QueryBuilderOptions();
// t.options.db = String; -- database/collection/table
// t.options.exec = String; -- operation name (find/insert/remove/etc..)
// t.options.payload = {};
// t.options.upsert = Boolean;
// t.options.fields = String Array;
// t.options.sort = String Array; -- in the form: field_asc, field_desc
// t.options.take = Number;
// t.options.skip = Number;
// t.options.filter = Object Array -- types: where/in/notin/or/between/contains/empty
t.options.filter = [];
}
function execdb(db) {
var conn = F.querybuilders[db.conn] || F.querybuilders['*'];
if (conn) {
if (db.options.checksum)
db.options.checksum = HASH(db.options.checksum).toString(36);
conn.call(db, db.options, (err, response) => db.evaluate(err, response));
} else
db.evaluate('Database is not initialized');
}
function QueryBuilder(main, table, exec) {
var t = this;
t.main = main;
t.options = main.options;
t.options.checksum = '';
t.options.table = table;
t.options.exec = exec;
t.filter = t.options.filter;
if (exec === 'list') {
t.options.skip = 0;
t.options.take = 100;
}
if (exec === 'read') {
t.options.take = 1;
t.options.first = true;
}
var ctrl = main.controller;
if (!ctrl.commands) {
setImmediate(execdb, main);
return;
}
if (ctrl.$debug)
t.options.debug = true;
if (ctrl.$end) {
ctrl.$end = false;
setImmediate(ctrl.next, ctrl);
}
}
var CTP = Controller.prototype;
var DBP = DB.prototype;
var QBP = QueryBuilder.prototype;
function parsedb(table) {
var index = table.indexOf('/');
return index === -1 ? { db: 'default', table: table } : { db: table.substring(0, index), table: table.substring(index + 1) };
}
CTP.language = function(prefix, skip) {
LANGUAGE_PREFIX = prefix;
LANGUAGE_SKIP = skip;
return this;
};
CTP.exec = function(filter, callback) {
var t = this;
var builder;
switch (filter.exec) {
case 'find':
case 'list':
case 'read':
case 'count':
case 'truncate':
case 'drop':
case 'remove':
case 'insert':
case 'update':
case 'scalar':
case 'command':
builder = t[filter.exec](filter.table);
for (var key in filter) {
if (key !== 'table')
builder.options[key] = filter[key];
}
builder.callback(callback);
break;
case 'query':
builder = t[filter.exec](filter.table, filter.query);
for (var key in filter) {
if (key !== 'table' && key !== 'query')
builder.options[key] = filter[key];
}
builder.callback(callback);
break;
}
};
CTP.next = function(t) {
if (t.error) {
t.$callback && t.$callback(t.error, null);
t.free();
return;
}
if (t.commands) {
var item = t.commands.shift();
if (item) {
execdb(item);
return;
}
}
t.$callback && t.$callback(t.error, t.response);
t.$end = true;
};
CTP.callback = CTP.pipe = function($) {
var t = this;
t.$callback = typeof($) === 'function' ? $ : $.callback();
return t;
};
CTP.promise = function($) {
var t = this;
var promise = new Promise(function(resolve, reject) {
t.$callback = function(err, response) {
if (err) {
if ($ && $.invalid) {
$.invalid(err);
t.free();
} else {
reject(err);
}
} else
resolve(response);
};
});
return promise;
};
CTP.done = function($, callback) {
var t = this;
t.$callback = function(err, response) {
if (err)
$.invalid(err);
else
callback && callback(response);
t.free();
};
return t;
};
CTP.free = function() {
var t = this;
t.commands = t.$callback = t.$fail = t.$data = t.response = t.error = null;
};
CTP.load = function(conn, opt) {
if (!opt) {
opt = conn;
conn = 'default';
}
var t = this;
var db = new DB(conn);
db.controller = t;
t.commands && t.commands.push(db);
var builder = new QueryBuilder(db, opt.table, opt.exec);
builder.options.fields = opt.fields && opt.fields instanceof Array && opt.fields.length ? opt.fields : null;
builder.options.skip = opt.skip;
builder.options.take = opt.take;
builder.options.query = opt.query;
builder.options.sort = opt.sort && opt.sort instanceof Array && opt.sort.length ? opt.sort : null;
builder.options.payload = opt.payload;
builder.options.upsert = opt.upsert;
builder.options.returning = opt.returning;
builder.options.filter = opt.filter && opt.filter instanceof Array ? opt.filter : EMPTYARRAY;
return builder;
};
CTP.find = CTP.all = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'find');
};
CTP.debug = function() {
this.$debug = true;
return this;
};
CTP.list = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var db = new DB(meta.db);
var t = this;
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'list');
};
CTP.check = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
var builder = new QueryBuilder(db, meta.table, 'check');
builder.options.take = builder.options.first = 1;
return builder;
};
CTP.read = CTP.one = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'read');
};
CTP.count = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'count');
};
CTP.scalar = function(table, type, key, key2) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
if (key == null)
key = '*';
var db = new DB(meta.db);
db.options.scalar = {};
db.options.scalar.type = type;
if (key)
db.options.scalar.key = key;
if (key2)
db.options.scalar.key2 = key2;
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'scalar');
};
CTP.insert = CTP.ins = function(table, data) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
db.options.payload = data;
return new QueryBuilder(db, meta.table, 'insert');
};
CTP.update = CTP.modify = CTP.mod = CTP.upd = function(table, data, upsert) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.options.payload = data;
db.options.upsert = upsert;
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'update');
};
CTP.remove = CTP.rem = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'remove');
};
CTP.query = function(table, query, params) {
if (query == null || typeof(query) === 'object') {
params = query;
query = table;
table = 'default/';
} else
table += '/';
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
db.options.query = query;
db.options.params = params;
return new QueryBuilder(db, '', 'query');
};
CTP.drop = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var t = this;
var db = new DB(meta.db);
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'drop');
};
CTP.truncate = CTP.clear = function(table) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var db = new DB(meta.db);
var t = this;
db.controller = t;
t.commands && t.commands.push(db);
return new QueryBuilder(db, meta.table, 'truncate');
};
CTP.command = function(table, name) {
var meta = F.temporary.querybuilders[table] || (F.temporary.querybuilders[table] = parsedb(table));
var db = new DB(meta.db);
var t = this;
db.controller = t;
t.commands && t.commands.push(db);
db.options.command = name;
return new QueryBuilder(db, meta.table, 'command');
};
DBP.evaluate = function(err, response) {
var t = this;
if (t.options.first && response instanceof Array)
response = response.length ? response[0] : null;
if (!err && t.error) {
if (t.error_reverse) {
if (response)
err = t.error;
else if (!t.options.first && response instanceof Array && response.length)
err = t.error;
} else if (!response)
err = t.error;
else if (!t.options.first && response instanceof Array && !response.length)
err = t.error;
}
// Upsert
if (!err && t.options.exec === 'update' && t.options.upsert) {
var is = false;
if (t.options.returning) {
if (t.options.first) {
if (!response)
is = true;
} else {
if (!response.length)
is = true;
}
} else if (!response)
is = true;
if (is) {
t.$insert && t.$insert(t.options.payload, t.$insertparam);
t.options.exec = 'insert';
t.options.filter.length = 0;
execdb(t);
return;
}
}
if (!err && t.options.exec === 'list') {
response.page = (t.options.skip / t.options.take) + 1;
response.limit = t.options.take;
response.pages = Math.ceil(response.count / t.options.take);
}
if (t.controller) {
t.controller.error = err;
if (!t.$nobind) {
if (t.output)
t.controller.response[t.output] = response;
else
t.controller.response = response;
}
}
if (err) {
t.callback_fail && t.callback_fail(err);
} else {
if (t.$audit) {
t.$audit();
t.$audit = null;
}
t.callback_data && t.callback_data(response);
}
t.callback && t.callback(err, response);
t.controller && setImmediate(t.controller.next, t.controller);
};
QBP.audit = function($, message, type) {
var self = this;
self.main.$audit = function() {
// Dynamic arguments
if (message)
message = $.variables(message, self.options.payload);
$.audit(message, type);
};
return self;
};
QBP.promise = function($) {
var t = this;
var promise = new Promise(function(resolve, reject) {
t.main.callback = function(err, response) {
if (err) {
if ($ && $.invalid) {
$.invalid(err);
t.main.controller && t.main.controller.free();
} else {
err.name = 'QueryBuilder(' + t.options.table + ' --> ' + t.options.exec + ')';
reject(err);
}
} else
resolve(response);
};
});
return promise;
};
QBP.insert = function(callback, param) {
this.main.$insert = callback;
this.main.$insertparam = param;
return this;
};
QBP.set = function(name) {
this.main.output = name;
return this;
};
QBP.callback = QBP.pipe = function($) {
var t = this;
t.main.callback = typeof($) === 'function' ? $ : $.callback();
return t;
};
QBP.returning = function(fields) {
var key = '_' + fields;
if (!F.temporary.querybuilders[key]) {
var arr = [];
fields = fields.split(',');
for (var field of fields) {
field = field.trim();
arr.push(field);
}
F.temporary.querybuilders[key] = arr;
}
this.options.returning = F.temporary.querybuilders[key];
return this;
};
QBP.nobind = function() {
this.main.$nobind = true;
return this;
};
QBP.data = function(cb) {
this.main.callback_data = cb;
return this;
};
QBP.fail = function(cb) {
this.main.callback_fail = cb;
return this;
};
QBP.error = QBP.err = function(err, reverse) {
this.main.error = err + '';
this.main.error_reverse = reverse;
return this;
};
QBP.done = function($, callback, param) {
this.main.callback = function(err, response) {
if (err)
$.invalid(err);
else
callback(response, param);
};
return this;
};
QBP.id = function(id) {
return id instanceof Array ? this.in('id', id) : this.where('id', id);
};
QBP.userid = function(id) {
return id instanceof Array ? this.in('userid', id) : this.where('userid', typeof(id) === 'string' ? id : (id.user ? id.user.id : id.id));
};
QBP.equal = function(obj) {
for (var key in obj)
this.where(key, obj[key]);
return this;
};
QBP.where = function(name, comparer, value) {
var t = this;
if (comparer === undefined && value === undefined)
return t.query(name);
if (value === undefined) {
value = comparer;
comparer = '=';
}
switch (comparer) {
case '==':
comparer = '=';
break;
case '!=':
comparer = '<>';
break;
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'where' + comparer + name;
t.filter.push({ type: 'where', name: name, comparer: comparer, value: value });
return t;
};
QBP.array = function(name, comparer, value) {
var t = this;
if (value === undefined) {
value = comparer;
comparer = '&&';
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'array' + comparer + name;
t.filter.push({ type: 'array', name: name, comparer: comparer, value: value });
return t;
};
QBP.take = function(count) {
this.options.take = count;
return this;
};
QBP.first = function() {
this.options.take = this.options.first = 1;
return this;
};
QBP.limit = function(count) {
this.options.take = count;
return this;
};
QBP.language = function(val, prefix, skip) {
var self = this;
if (!skip)
skip = LANGUAGE_SKIP;
if (val && typeof(val) === 'object')
val = val.language;
if (skip && val && val === skip) {
val = '';
prefix = '';
}
if (val != null)
self.options.language = (prefix == null ? LANGUAGE_PREFIX : prefix) + val;
return self;
};
QBP.debug = function() {
this.options.debug = true;
return this;
};
QBP.page = function(page, limit) {
if (limit)
this.options.take = limit;
this.options.skip = (page - 1) * this.options.take;
return this;
};
QBP.paginate = function(page, limit, maxlimit) {
var limit2 = +(limit || 0);
var page2 = (+(page || 0)) - 1;
if (page2 < 0)
page2 = 0;
if (maxlimit && limit2 > maxlimit)
limit2 = maxlimit;
if (!limit2)
limit2 = maxlimit;
this.options.skip = page2 * limit2;
this.options.take = limit2;
return this;
};
QBP.primarykey = function(val) {
this.options.primarykey = val;
return this;
};
QBP.skip = function(count) {
this.options.skip = count;
return this;
};
QBP.in = function(name, value, id) {
var t = this;
if (id) {
var arr = [];
for (var i = 0; i < value.length; i++)
arr.push(value[i][id]);
value = arr;
}
if (!(value instanceof Array))
value = [value];
t.options.checksum += (t.options.checksum ? ' ' : '') + 'in=' + name;
t.filter.push({ type: 'in', name: name, value: value });
return t;
};
QBP.notin = function(name, value, id) {
var t = this;
if (id) {
var arr = [];
for (var i = 0; i < value.length; i++)
arr.push(value[i][id]);
value = arr;
}
if (!(value instanceof Array))
value = [value];
t.options.checksum += (t.options.checksum ? ' ' : '') + 'notin=' + name;
t.filter.push({ type: 'notin', name: name, value: value });
return t;
};
QBP.between = function(name, a, b) {
var t = this;
t.options.checksum += (t.options.checksum ? ' ' : '') + 'between=' + name;
t.filter.push({ type: 'between', name: name, a: a, b: b });
return t;
};
QBP.or = function(callback) {
var t = this;
var filter = t.filter;
t.filter = [];
t.options.checksum += (t.options.checksum ? ' ' : '') + 'or(';
callback.call(t, t);
if (t.filter.length) {
filter.push({ type: 'or', value: t.filter });
}
t.options.checksum += ')';
t.filter = filter;
return t;
};
QBP.fields = function(fields) {
var t = this;
var key = '_' + fields;
if (!F.temporary.querybuilders[key]) {
var arr = [];
fields = fields.split(',');
for (var field of fields) {
field = field.trim();
arr.push(field);
}
F.temporary.querybuilders[key] = arr;
}
t.options.fields = F.temporary.querybuilders[key];
return t;
};
QBP.month = function(name, comparer, value) {
var t = this;
if (value === undefined) {
value = comparer;
comparer = '=';
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'month' + comparer + name;
t.filter.push({ type: 'month', name: name, comparer: comparer, value: value });
return t;
};
QBP.day = function(name, comparer, value) {
var t = this;
if (value === undefined) {
value = comparer;
comparer = '=';
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'day' + comparer + name;
t.filter.push({ type: 'day', name: name, comparer: comparer, value: value });
return t;
};
QBP.year = function(name, comparer, value) {
var t = this;
if (value === undefined) {
value = comparer;
comparer = '=';
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'year' + comparer + name;
t.filter.push({ type: 'year', name: name, comparer: comparer, value: value });
return t;
};
QBP.hour = function(name, comparer, value) {
var t = this;
if (value === undefined) {
value = comparer;
comparer = '=';
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'hour' + comparer + name;
t.filter.push({ type: 'hour', name: name, comparer: comparer, value: value });
return t;
};
QBP.minute = function(name, comparer, value) {
var t = this;
if (value === undefined) {
value = comparer;
comparer = '=';
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'minute' + comparer + name;
t.filter.push({ type: 'minute', name: name, comparer: comparer, value: value });
return t;
};
QBP.search = function(name, value, where) {
var t = this;
t.options.checksum += (t.options.checksum ? ' ' : '') + 'search=' + name + '=' + (where || '');
t.filter.push({ type: 'search', name: name, comparer: where, value: value });
return t;
};
QBP.contains = function(name) {
var t = this;
t.options.checksum += (t.options.checksum ? ' ' : '') + 'contains=' + name;
t.filter.push({ type: 'contains', name: name });
return t;
};
QBP.empty = function(name) {
var t = this;
t.options.checksum += (t.options.checksum ? ' ' : '') + 'empty=' + name;
t.filter.push({ type: 'empty', name: name });
return t;
};
// Converting values
var convert = function(value, type) {
if (type === undefined || type === String)
return value;
if (type === Number)
return value.trim().parseFloat();
if (type === Date) {
value = value.trim();
if (value.indexOf(' ') !== -1)
return NOW.add('-' + value);
if (value.length < 8) {
var tmp;
var index = value.indexOf('-');
if (index !== -1) {
tmp = value.split('-');
value = NOW.getFullYear() + '-' + (tmp[0].length > 1 ? '' : '0') + tmp[0] + '-' + (tmp[1].length > 1 ? '' : '0') + tmp[1];
} else {
index = value.indexOf('.');
if (index !== -1) {
tmp = value.split('.');
value = NOW.getFullYear() + '-' + (tmp[1].length > 1 ? '' : '0') + tmp[0] + '-' + (tmp[0].length > 1 ? '' : '0') + tmp[1];
} else {
index = value.indexOf(':');
if (index !== -1) {
// hours
} else if (value.length <= 4) {
value = +value;
return value || 0;
}
}
}
}
return value.trim().parseDate();
}
if (type === Boolean)
return value.trim().parseBoolean();
return value;
};
QBP.gridfields = function(fields, allowed) {
var t = this;
var count = 0;
var newfields = [];
fields = fields.replace(REG_FIELDS_CLEANER, '').split(',');
if (allowed)
allowed = allowed.split(',');
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var can = !allowed;
if (!can) {
for (var j = 0; j < allowed.length; j++) {
if (allowed[j] === field) {
can = true;
break;
}
}
}
if (can) {
newfields.push(fields[i]);
count++;
}
}
if (!count)
t.options.fields = newfields;
return t;
};
// Grid filtering
QBP.gridfilter = function(name, obj, type, key) {
let builder = this;
let value = obj[name] || '';
if (!value || typeof(value) !== 'string')
return builder;
let arr, val;
if (!key)
key = name;
if (typeof(type) === 'string') {
switch (type) {
case 'string':
type = String;
break;
case 'date':
case 'datetime':
type = Date;
break;
case 'number':
case 'decimal':
case 'float':
type = Number;
break;
case 'boolean':
case 'bool':
type = Boolean;
break;
case '[string]':
return builder.array(key, value);
case 'json':
return builder.search(key, value);
}
}
// Between
let index = value.indexOf(' - ');
if (index !== -1) {
arr = value.split(' - ');
for (let i = 0, length = arr.length; i < length; i++) {
let item = arr[i].trim();
arr[i] = convert(item, type);
}
if (type === Date) {
if (typeof(arr[0]) === 'number') {
arr[0] = new Date(arr[0], 1, 1, 0, 0, 0);
arr[1] = new Date(arr[1], 11, 31, 23, 59, 59);
} else
arr[1] = arr[1].extend('23:59:59');
}
return builder.between(key, arr[0], arr[1]);
}
// Multiple values
index = value.indexOf(',');
if (index !== -1) {
let exact = value[0] === '=';
let arr = (exact ? value.substring(1) : value).split(',');
if (type === undefined || type === String) {
if (exact) {
for (let i = 0; i < arr.length; i++)
arr[i] = arr[i].trim();
builder.in(key, arr);
} else {
builder.or(function() {
for (let i = 0; i < arr.length; i++) {
let item = arr[i].trim();
builder.search(key, item);
}
});
}
return builder;
}
for (let i = 0; i < arr.length; i++)
arr[i] = convert(arr[i], type);
return builder.in(key, arr);
}
if (type === undefined || type === String)
return value[0] === '=' ? builder.where(key, '=', value.substring(1)) : builder.search(key, value);
let comparer = '=';
switch (value[0]) {
case '>':
case '<':
comparer = value[0];
value = value.substring(1);
break;
}
if (type === Date) {
if (value === 'yesterday')
val = NOW.add('-1 day');
else if (value === 'today')
val = NOW;
else
val = convert(value, type);
if (typeof(val) === 'number') {
if (val > 1000)
return builder.year(key, comparer, val);
else
return builder.month(key, comparer, val);
}
if (!(val instanceof Date) || !val.getTime())
val = NOW;
return comparer === '=' ? builder.between(key, val.extend('00:00:00'), val.extend('23:59:59')) : builder.where(key, comparer, val);
}
return builder.where(key, comparer, convert(value, type));
};
QBP.sort = function(sort, type) {
var t = this;
if (!t.options.sort)
t.options.sort = [];
t.options.sort.push(sort + '_' + (type === true || type === 'desc' ? 'desc' : 'asc'));
return t;
};
QBP.gridsort = function(sort, localized) {
var t = this;
if (!t.options.sort)
t.options.sort = [];
var keys = sort.split(',');
for (var key of keys) {
key = key.trim();
var index = key.lastIndexOf('_');
var field = '';
var sort = '';
if (index === -1) {
field = key;
sort = 'asc';
} else {
field = key.substring(0, index);
sort = key.substring(index + 1);
}
if (localized && localized[field])
field = localized[field];
//t.options.sort.push(index === -1 ? (key + '_asc') : key);
t.options.sort.push(field + '_' + sort);
}
return t;
};
QBP.schema = function(value) {
this.options.schema = value || '';
return this;
};
QBP.autoquery = function(query, schema, defsort, maxlimit) {
let t = this;
let skipped;
let key = 'QBF' + schema;
let allowed = F.temporary.querybuilders[key];
let tmp;
if (!allowed) {
let obj = {};
let arr = [];
let filter = [];
let localized = {};
if (schema.charAt(0) === '@') {
let jschema = F.jsonschemas[schema.substring(1)];
if (jschema) {
schema = '';
for (let key in jschema.properties) {
let prop = jschema.properties[key];
schema = (schema ? schema + ',' : '') + key + ':' + (prop.type === 'array' ? '[string]' : prop.type);
}
}
}
tmp = schema.split(',').trim();
for (let field of tmp) {
let k = field.split(':').trim();
arr.push(k[0]);
let cleaned = k[0].replace(/§/g, '');
obj[cleaned] = 1;
localized[cleaned] = k[0];
filter.push({ name: cleaned, type: (k[1] || 'string').toLowerCase() });
}
allowed = F.temporary.querybuilders[key] = { keys: arr, meta: obj, filter: filter, fields: localized };
}
let fields = query.fields;
let fieldscount = 0;
if (!t.options.fields)
t.options.fields = [];
if (fields) {
fields = fields.replace(REG_FIELDS_CLEANER, '').split(',');
for (let field of fields) {
if (allowed && allowed.meta[field]) {
t.options.fields.push(field);
fieldscount++;
}
}
}
if (!fieldscount) {
for (let field of allowed.keys)
t.options.fields.push(field);
}
if (allowed && allowed.filter) {
for (let item of allowed.filter)
t.gridfilter(item.name, query, item.type, allowed.fields[item.name]);
}
if (query.sort) {
tmp = query.sort.split(',');
let count = 0;
for (let item of tmp) {
let index = item.lastIndexOf('_');
let name = index === - 1 ? item : item.substring(0, index);
if ((skipped && skipped[name]) || (!allowed.meta[name]))
continue;
t.sort(allowed.fields[name], item[index + 1] === 'd');
count++;
}
if (!count && defsort)
t.gridsort(defsort, allowed.fields);
} else if (defsort)
t.gridsort(defsort, allowed.fields);
maxlimit && t.paginate(query.page, query.limit, maxlimit);
return t;
};
QBP.query = function(value) {
this.filter.push({ type: 'query', value: value });
return this;
};
QBP.join = function(name, table, jointype, a, b) {
this.filter.push({ type: 'join', table: table, name: name, join: jointype, on: [a, b] });
return this;
};
QBP.permit = function(name, type, value, userid, required) {
// type: R read
// type: W write
// type: D delete
var t = this;
var types = type.split('');
var arr = [];
if (value && value.length) {
for (let m of value) {
for (let n of types)
arr.push(n + m);
}
}
t.options.checksum += (t.options.checksum ? ' ' : '') + 'permit' + type + arr.join('');
t.filter.push({ type: 'permit', name: name, value: arr, userid: userid, required: required != false });
return t;
};
exports.create = function(type, callback) {
if (typeof(type) === 'function') {
callback = type;
type = 'default';
}
if (callback)
F.querybuilders[type] = callback;
else
delete F.querybuilders[type];
};
exports.Controller = Controller;
exports.QueryBuilder = QueryBuilder;