yalento
Version:
An awesome integration of Google Firebase for Angular and Node
328 lines (327 loc) • 13.2 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuerySubject = void 0;
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const QueryPaginator_1 = require("./query/QueryPaginator");
//eslint-disable-next-line @typescript-eslint/no-var-requires
const alasql = require('alasql');
/**
* INTERNAL USE ONLY
*/
class QuerySubject {
/**
*
* @param repository
* @param sql
* @param paginatorDefaults
*/
constructor(repository, sql, paginatorDefaults) {
this.repository = repository;
this._lastExecStatement = '';
this._subscriptions = [];
this._repositoryLastCount = 0;
this.uuid = '';
this.queryCallbackChanges$ = new rxjs_1.BehaviorSubject({});
this.paginator = new QueryPaginator_1.QueryPaginator(this);
if (sql) {
this._sql = sql;
}
if (paginatorDefaults) {
this._paginatorDefaults = paginatorDefaults;
}
this.setPaginatorDefaults(this._paginatorDefaults, this._sql);
this.observeStatement(this._sql);
this.observeQueryCallbackChanges(this._sql).then().catch();
}
unsubscribe() {
this._subscriptions.forEach((sub) => {
sub.unsubscribe();
});
}
getSql() {
return this._sql;
}
getSqlSelectParsed(sql) {
let statement = '';
const params = this.getEvaluatedSqlParams(sql);
const querySelect = 'SELECT * FROM tmptablenametmp';
if (!sql) {
sql = {};
}
if (sql.where) {
statement += ' WHERE ' + sql.where;
}
let selectSqlStatement = alasql.parse(querySelect + statement, params).toString();
if (params) {
params.forEach((value, index) => {
selectSqlStatement = selectSqlStatement.replace('$' + index, typeof value === 'string' ? "'" + value + "'" : value);
});
}
let ownerWhere = '';
if (this.getRepository().isPrivateMode()) {
ownerWhere += ' `__owner.' + this.getUserUuid() + '` = true ';
}
else {
ownerWhere += ' `__owner.EVERYBODY` = true ';
}
if (sql.excludeWhereIamOwner === true) {
ownerWhere += ' AND `__owner.' + this.getUserUuid() + '` IS NULL ';
}
if (sql.includeWhereIamOwner === true) {
ownerWhere += ' AND `__owner.' + this.getUserUuid() + '` = true ';
}
if (sql.where) {
selectSqlStatement =
querySelect + ' WHERE (' + ownerWhere + ') AND (' + selectSqlStatement.substr(querySelect.length + 6) + ')';
}
else {
selectSqlStatement = selectSqlStatement + ' WHERE ' + ownerWhere;
}
return selectSqlStatement.replace(/tmptablenametmp/g, this.repository.getClassName());
}
/**
*
* @param sql
* @param skipConnectors
* @param skipGeolocation
*/
execStatement(sql, skipConnectors, skipGeolocation) {
return __awaiter(this, void 0, void 0, function* () {
this.uuid = this.getRepository().getUserUuid();
if (((sql && sql.excludeWhereIamOwner === true) ||
(sql && sql.includeWhereIamOwner === true) ||
this.getRepository().isPrivateMode()) &&
this.uuid === null) {
yield this.getRepository().getUserUuidObservable().pipe(operators_1.take(1)).toPromise();
this.uuid = this.getRepository().getUserUuid();
}
let statement = '';
const selectSqlStatement = this.getSqlSelectParsed(sql);
const params = this.getEvaluatedSqlParams(sql);
if (selectSqlStatement.indexOf('LIKE null') > 0) {
return rxjs_1.of([]).toPromise();
}
if (!skipConnectors && this._lastExecStatement !== selectSqlStatement + this.repository.getGeoQuery()) {
this.repository.loadQueryFromConnectors(selectSqlStatement);
this._lastExecStatement = selectSqlStatement + this.repository.getGeoQuery();
}
if (this._repositoryLastCount === 0 && this.repository.count() === 0) {
return rxjs_1.of([]).toPromise();
}
this._repositoryLastCount = this.repository.count();
if (!sql) {
sql = {};
}
if (this.repository.getGeoQuery() && !skipGeolocation) {
statement += ' WHERE __removed = false ' + this.repository.getGeoQuery() + ' AND ( ';
}
else {
statement += ' WHERE __removed = false AND ( ';
}
if (this.getRepository().isPrivateMode()) {
statement += '"' + this.getUserUuid() + '" IN __owner ';
}
else {
statement += '"EVERYBODY" IN __owner ';
if (this.getUserUuid() !== 'null') {
statement += ' OR "' + this.getUserUuid() + '" IN __owner ';
}
}
statement += ' ) ';
if (sql.where) {
statement += ' AND (' + sql.where + ')';
}
if (sql.excludeWhereIamOwner === true) {
statement += ' AND "' + this.getUserUuid() + '" IN __owner = false';
}
if (sql.includeWhereIamOwner === true) {
statement += ' AND "' + this.getUserUuid() + '" IN __owner = true';
}
if (this.getPaginator().getPageSortProperty() !== '' && this.getPaginator().getPageSortDirection() !== '') {
statement +=
' ORDER BY ' + this.getPaginator().getPageSortProperty() + ' ' + this.getPaginator().getPageSortDirection();
}
else if (sql.orderBy) {
statement += ' ORDER BY ' + sql.orderBy;
}
statement = this.replaceStatement(statement);
const resultsAll = alasql('SELECT * FROM ' + this.repository.getTableName() + ' ' + statement, params).map((d) => d._ref);
const count = alasql('SELECT COUNT(*) as c FROM ' + this.repository.getTableName() + ' ' + statement, params)[0]['c'];
if (sql.limit && !this.getPaginator().hasPageSizeChanges()) {
statement += ' LIMIT ' + sql.limit;
}
else if (this.getPaginator().getPageSize()) {
statement += ' LIMIT ' + this.getPaginator().getPageSize();
}
if (sql.offset) {
if (sql.limit === undefined) {
statement += ' LIMIT 1';
}
statement += ' OFFSET ' + sql.offset;
}
else {
if (count && this.getPaginator().getPageIndex() * this.getPaginator().getPageSize() > count) {
this.getPaginator().setPageIndex(Math.floor(count / this.getPaginator().getPageSize()));
}
if (this.getPaginator().getPageIndex() * this.getPaginator().getPageSize()) {
statement += ' OFFSET ' + this.getPaginator().getPageIndex() * this.getPaginator().getPageSize();
}
}
const results = alasql('SELECT _ref FROM ' + this.repository.getTableName() + ' ' + statement, params).map((d) => d._ref);
this._lastExecStatement = selectSqlStatement;
this.updateQueryCallbackChanges({
resultsAll: resultsAll,
results: results,
count: count,
});
return rxjs_1.of(results).toPromise();
});
}
/**
* get behaviour subject
*/
getPaginator() {
return this.paginator;
}
/**
* update query callback changes
*/
updateQueryCallbackChanges(changes) {
if (Object.keys(changes).length > 0) {
this.queryCallbackChanges$.next(changes);
}
}
/**
* get query callback changes observer
*/
getQueryCallbackChanges() {
return this.queryCallbackChanges$;
}
/**
*
*/
getRepository() {
return this.repository;
}
/**
*
*/
getUserUuid() {
return this.getRepository().getUserUuid();
}
/**
*
* @param sql
*/
getEvaluatedSqlParams(sql) {
let params = sql && sql.params !== undefined ? sql.params : null;
if (params) {
const tmpParams = [];
params.forEach((param) => {
if (param &&
typeof param === 'object' &&
param.asObservable !== undefined &&
typeof param.asObservable === 'function' &&
typeof param.getValue === 'function') {
tmpParams.push(param.getValue());
}
else {
tmpParams.push(param);
}
});
params = tmpParams;
}
return params;
}
/**
*
* @param paginatorDefaults
* @param sql
*/
setPaginatorDefaults(paginatorDefaults, sql) {
if (paginatorDefaults && paginatorDefaults.pageSizeOptions) {
this.getPaginator().setPageSizeOptions(paginatorDefaults.pageSizeOptions);
if (paginatorDefaults.pageSize === undefined) {
this.getPaginator().setPageSize(paginatorDefaults.pageSizeOptions[0]);
}
}
if (paginatorDefaults && paginatorDefaults.pageSort) {
this.getPaginator().setPageSort(paginatorDefaults.pageSort);
}
if (paginatorDefaults && paginatorDefaults.pageSize) {
this.getPaginator().setPageSize(paginatorDefaults.pageSize, true);
if (this.getPaginator().getPageSizeOptions().indexOf(this.getPaginator().getPageSize()) < 0) {
this.getPaginator().addPageSizeOption(paginatorDefaults.pageSize);
}
}
else if (sql && sql.limit) {
this.getPaginator().setPageSize(sql.limit, true);
}
}
/**
* observe and re-execute statement on any changes
* @param sql
*/
observeStatement(sql) {
if (sql && sql.params) {
sql.params.forEach((param) => {
if (param &&
typeof param === 'object' &&
param.asObservable !== undefined &&
typeof param.asObservable === 'function') {
this._subscriptions.push(param.asObservable().subscribe(() => {
this.updateQueryCallbackChanges({ selectSqlStatement: true });
}));
}
});
}
return;
}
/**
* observe queryCallbackChanges$
*/
observeQueryCallbackChanges(sql) {
return new Promise((resolve) => {
this._subscriptions.push(this.queryCallbackChanges$.subscribe((changes) => __awaiter(this, void 0, void 0, function* () {
if (changes.geoLocationChanged ||
changes.dataAdded ||
changes.dataRemoved ||
changes.dataUpdated ||
changes.pageSize !== undefined ||
changes.pageIndex !== undefined ||
changes.pageSort !== undefined ||
changes.selectSqlStatement !== undefined) {
if (changes.geoLocationChanged) {
this._lastExecStatement = '';
}
this.execStatement(sql);
}
})));
});
}
/**
*
* @param statement
*/
replaceStatement(statement) {
this.repository.getClassProperties().forEach((property) => {
statement = statement.replace(new RegExp('\\(' + property.name + '->', 'gm'), '(_ref->' + property.name + '->');
statement = statement.replace(new RegExp(' ' + property.name + '->', 'gm'), ' _ref->' + property.name + '->');
statement = statement.replace(new RegExp(' ' + property.name + ' ', 'gm'), ' _ref->' + property.name + ' ');
statement = statement.replace(new RegExp('\\(' + property.name + ' ', 'gm'), '(_ref->' + property.name + ' ');
});
statement = statement.replace('__distance', '_ref->__distance');
return statement;
}
}
exports.QuerySubject = QuerySubject;