UNPKG

nextpay-querystring

Version:

Thư viện QueryString của NextPay - Chuyển đổi QueryString thành điều kiện select cho MongoDB và MySQL với kiểm soát bảo mật

156 lines 6.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable no-continue */ /* eslint-disable operator-linebreak */ /* eslint-disable implicit-arrow-linebreak */ const clauses_1 = require("./clauses"); const tokens_1 = require("../models/tokens"); const generics_1 = require("../utils/generics"); const exceptions_1 = require("../utils/exceptions"); const filters_1 = require("./filters"); // token-types order: // OR: 8 // AND: 7 // ===: 6 // IN, NIN, RANGE: 5 // == != < <= > >=: 4 // NOT: 2 const FULLMATCH_FILTER_LEVEL = 6; const ARRAY_FILTER_LEVEL = 5; const COMPARE_FILTER_LEVEL = 4; const NOT_CLAUSE_LEVEL = 2; const precedenceRules = [ [tokens_1.TokenType.OR, 8], [tokens_1.TokenType.AND, 7], [tokens_1.TokenType.TRIPLE_EQUALS, 6], [tokens_1.TokenType.IN, 5], [tokens_1.TokenType.NIN, 5], [tokens_1.TokenType.RANGE, 5], [tokens_1.TokenType.DOUBLE_EQUALS, 4], [tokens_1.TokenType.BANG_EQUAL, 4], [tokens_1.TokenType.LESS, 4], [tokens_1.TokenType.LESS_EQUAL, 4], [tokens_1.TokenType.GREATER, 4], [tokens_1.TokenType.GREATER_EQUAL, 4], [tokens_1.TokenType.PREFIX_LIKE, 4], [tokens_1.TokenType.MIDDLE_LIKE, 4], [tokens_1.TokenType.SUFFIX_LIKE, 4], [tokens_1.TokenType.NOT, 2], ]; const parseFuncPath = 'step2.Step2Converter.convert: '; const getRightParentAt = (0, generics_1.matchingElemPosition)({ type: tokens_1.TokenType.LEFT_PAREN, lexeme: '(' }, { type: tokens_1.TokenType.RIGHT_PAREN, lexeme: ')' })((x, y) => x.type === y.type && x.lexeme === y.lexeme); const getRightBracketAt = (0, generics_1.findFirst)({ type: tokens_1.TokenType.RIGHT_BRACKET, lexeme: ']', })((x, y) => x.type === y.type && x.lexeme === y.lexeme); const and = (tokens, leftId, rightId) => { let lastIndex = leftId - 1; const nodes = []; for (let i = leftId; i < rightId; i += 1) { if (tokens[i]?.type === tokens_1.TokenType.LEFT_PAREN) { i = getRightParentAt(tokens, i, rightId, []); } if (tokens[i]?.type !== tokens_1.TokenType.AND) continue; nodes.push(buildAST(tokens, lastIndex + 1, i)); lastIndex = i; } nodes.push(buildAST(tokens, lastIndex + 1, rightId)); return new clauses_1.AndClause(nodes); }; const or = (tokens, leftId, rightId) => { let lastIndex = leftId - 1; const nodes = []; for (let i = leftId; i < rightId; i += 1) { if (tokens[i]?.type === tokens_1.TokenType.LEFT_PAREN) { i = getRightParentAt(tokens, i, rightId, []); } if (tokens[i]?.type !== tokens_1.TokenType.OR) continue; nodes.push(buildAST(tokens, lastIndex + 1, i)); lastIndex = i; } nodes.push(buildAST(tokens, lastIndex + 1, rightId)); return new clauses_1.OrClause(nodes); }; const not = (tokens, leftId, rightId) => { const notSubGroup = tokens[leftId + 1]?.type !== tokens_1.TokenType.LEFT_PAREN && getRightParentAt(tokens, leftId + 1, rightId, []) !== rightId - 1; if (tokens[leftId]?.type !== tokens_1.TokenType.NOT || notSubGroup) { throw (0, exceptions_1.notCorrectPiecesException)(parseFuncPath, leftId, rightId)(NOT_CLAUSE_LEVEL); } return new clauses_1.NotClause(buildAST(tokens, leftId + 2, rightId - 1)); }; const fullmatchOpr = (tokens, leftId, rightId) => { const op = tokens[rightId - 2]; const str = tokens[rightId - 1]; const notArray = tokens[leftId]?.type !== tokens_1.TokenType.LEFT_BRACKET || getRightBracketAt(tokens, leftId, rightId, []) !== rightId - 3; if (op?.type !== tokens_1.TokenType.TRIPLE_EQUALS || str?.type !== tokens_1.TokenType.STRING || notArray) { throw (0, exceptions_1.notCorrectPiecesException)(parseFuncPath, leftId, rightId)(FULLMATCH_FILTER_LEVEL); } return new filters_1.FmFilter(tokens.slice(leftId + 1, rightId - 3), str); }; const compareFilter = (tokens, leftId, rightId) => { if (rightId - leftId !== 3 || tokens[leftId]?.type !== tokens_1.TokenType.VARIABLE) { throw (0, exceptions_1.notCorrectPiecesException)(parseFuncPath, leftId, rightId)(COMPARE_FILTER_LEVEL); } return (0, filters_1.compareFilterFactory)(tokens[leftId + 1])(tokens[leftId], tokens[rightId - 1]); }; const arrayFilter = (tokens, leftId, rightId) => { const notArray = tokens[leftId + 2]?.type !== tokens_1.TokenType.LEFT_BRACKET || getRightBracketAt(tokens, leftId, rightId, []) !== rightId - 1; if (tokens[leftId]?.type !== tokens_1.TokenType.VARIABLE || notArray) { throw (0, exceptions_1.notCorrectPiecesException)(parseFuncPath, leftId, rightId)(ARRAY_FILTER_LEVEL); } const values = tokens.slice(leftId + 3, rightId - 1); return (0, filters_1.arrayFilterFactory)(tokens[leftId + 1])(tokens[leftId], values); }; const precedenceOf = (type) => { const rule = precedenceRules.find(e => e[0] === type); if (!rule) { return -1; } return rule[1]; }; const buildAST = (tokens, leftId, rightId) => { if (leftId >= rightId) { throw (0, exceptions_1.outOfRangeException)(parseFuncPath, leftId, rightId); } const coveredByBracket = tokens[leftId]?.type === tokens_1.TokenType.LEFT_PAREN && getRightParentAt(tokens, leftId, rightId, []) === rightId - 1; if (coveredByBracket) { return buildAST(tokens, leftId + 1, rightId - 1); } let maxPrecedence = 0; for (let i = leftId; i < rightId; i += 1) { if (tokens[i]?.type === tokens_1.TokenType.LEFT_PAREN) { i = getRightParentAt(tokens, i, rightId, []); } else { maxPrecedence = Math.max(maxPrecedence, precedenceOf(tokens[i]?.type)); } } switch (maxPrecedence) { case 8: return or(tokens, leftId, rightId); case 7: return and(tokens, leftId, rightId); case 6: return fullmatchOpr(tokens, leftId, rightId); case 5: return arrayFilter(tokens, leftId, rightId); case 4: return compareFilter(tokens, leftId, rightId); case 2: return not(tokens, leftId, rightId); default: throw new Error('not existed'); } }; const parse = (tokens) => buildAST(tokens, 0, tokens.length); exports.default = parse; //# sourceMappingURL=parser.js.map