rsql-filter
Version:
Implementation of RSQL adapter for NodeJs ORM like TypeORM
21 lines (11 loc) • 4.71 kB
JavaScript
'use strict';
var typeorm = require('typeorm');
var Operator;!function(r){r.WHERE="w",r.AND=";",r.OR=",";}(Operator||(Operator={}));var Operation;!function(r){r.EQUALS="==",r.GREATER=">",r.MINOR="<",r.ILIKE="ILIKE",r.GREATER_THAN=">=",r.MINOR_THAN="<=",r.NOT_EQUALS="!=",r.IN="in",r.OUT="out";}(Operation||(Operation={}));var ORMType;!function(r){r.TYPE_ORM="typeOrm";}(ORMType||(ORMType={}));
class SQLOperation{}SQLOperation.equals="=",SQLOperation.greater=">",SQLOperation.greaterThan=">=",SQLOperation.minor="<",SQLOperation.minorThan="<=",SQLOperation.notEquals="!=",SQLOperation.in="IN",SQLOperation.notIn="NOT IN",SQLOperation.iLike="ILIKE";
function removeFirstChar(e){return e.substring(1)}function removeLastChar(e){return e.slice(0,-1)}function removeFirstLastCharacter(e){return e=removeLastChar(e=removeFirstChar(e))}function checkLike(e){return checkLikeStart(e=removeApostrophe(e))||checkLikeEnd(e)}function checkLikeStart(e){return "*"===e.charAt(0)}function checkLikeEnd(e){return "*"===e?.slice(-1)}function checkLikeAll(e){return checkLikeStart(e)&&checkLikeEnd(e)}function removeApostrophe(e){return e?.replace(/^'|'$/g,"")}
class TypeOrmQueryBuilder{static setOperators(e,t,r,a){return e.brackets?a=this.nestdOperator(e,t,r,a):this.setOpertor(e,t,r,a),a}static nestdOperator(e,t,r,a){const s={index:a};switch(e.operator){case Operator.AND:t.andWhere(this.setBrackets(e,r,s));break;case Operator.OR:t.orWhere(this.setBrackets(e,r,s));break;case Operator.WHERE:t.where(this.setBrackets(e,r,s));}return s.index}static setBrackets(e,t,r){return new typeorm.Brackets(a=>{const s=e.brackets;for(const e of s)e.brackets?r.index=this.setOperators(e,a,t,r.index):this.setOpertor(e,a,t,r.index),r.index++;})}static setOpertor(e,t,r,a){switch(e.operator){case Operator.AND:return t.andWhere(this.setOperatorContent(r,e,a),this.assignValue(e,a));case Operator.OR:return t.orWhere(this.setOperatorContent(r,e,a),this.assignValue(e,a));case Operator.WHERE:return t.andWhere(this.setOperatorContent(r,e,a),this.assignValue(e,a));default:return null}}static assignValue(e,t){const r={};return r[`op${t}`]=this.fixedValue(e.value),r}static setOperatorContent(e,t,r){return `${this.setAlias(e,t)}${t.prop} ${this.setOperation(t)} ${this.setParameter(t,r)}`}static setParameter(e,t){return e.value.startsWith("(")?`(:...op${t})`:`(:op${t})`}static setAlias(e,t){const r=t.prop?.includes(".");return r?"":`${e}.`}static fixedValue(e){if("string"==typeof e){if(e=removeApostrophe(e),checkLikeStart(e)&&!checkLikeEnd(e))return `%${removeFirstChar(e)}`;if(checkLikeEnd(e)&&!checkLikeStart(e))return `${removeLastChar(e)}%`;if(checkLikeAll(e))return `%${removeFirstLastCharacter(e)}%`;e.startsWith("(")&&(e=(e=removeFirstLastCharacter(e)).split(","));}return e}static setOperation(e){switch(e.operation){case Operation.EQUALS:return checkLike(e.value)?SQLOperation.iLike:SQLOperation.equals;case Operation.MINOR:return SQLOperation.minor;case Operation.GREATER:return SQLOperation.greater;case Operation.GREATER_THAN:return SQLOperation.greaterThan;case Operation.MINOR_THAN:return SQLOperation.minorThan;case Operation.NOT_EQUALS:case Operation.IN:return SQLOperation.in;case Operation.OUT:default:return SQLOperation.notIn}}}
class QueryBuilder{static setOperatorsByOrmType(r,e,t,p,y){return y===ORMType.TYPE_ORM?TypeOrmQueryBuilder.setOperators(r,e,t,p):p}}
class RSQLParser{static buildQuery(e,r,s){const t=e?.replace(/"/g,"'")?.replace(/\\\\'/g,"__REPLACED__");let i=t?.match(/\((\s*(?:'[^'\\]*(?:\\.[^'\\]*)*'|[^,'()]+)\s*(?:,\s*(?:'[^'\\]*(?:\\.[^'\\]*)*'|[^,'()]+)\s*)*)\)|"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|\*?[a-zA-Z0-9_.\-]+\*?|==|!=|>=|<=|>|<|;|,|\(|\)/g),a=[];i?.unshift("w"),i?.push("end");const l=r.alias;if(i){a=this.parseRSQL(i,a);let e=0;const t=a?.arr;for(const i of t)e=QueryBuilder.setOperatorsByOrmType(i,r,l,e,s),e++;}return r}static parseRSQL(e,r,s){const t={};t.operator=e[0];const i=e[1];if("("!=i&&(t.prop=e[1],t.operation=e[2],t.value=e[3]?.replace("__REPLACED__","'")),"("===i){t.brackets=[],t.isInBrackets=true,t.isAlreadySaved=true,t.livello=s?.livello?s?.livello+1:1,1===t.livello&&r?.push(t),(e=e.slice(2)).unshift(Operator.WHERE);e=this.parseRSQL(e,r,t).tokens;}if(s?.isInBrackets?(t.isBracket=true,s?.brackets?.push(t)):t.isAlreadySaved||r?.push(t),e=e.slice(4),e?.length>=4){this._fixToken(e,s);const t=this.parseRSQL(e,r,s?.isInBrackets?s:null);e=t.tokens,r=t.arr;}return {arr:r,tokens:e}}static _fixToken(e,r){return ")"===e[0]&&(e.shift(),r&&(r.isInBrackets=false),e=this._fixToken(e)),e}}
function rsqlTypeOrmFilter(r,e){return RSQLParser.buildQuery(r,e,ORMType.TYPE_ORM)}
exports.rsqlTypeOrmFilter = rsqlTypeOrmFilter;
//# sourceMappingURL=index.js.map