@bitovi/objection-querystring-parser
Advanced tools
Comparing version 0.1.2 to 0.1.3
@@ -1,5 +0,1 @@ | ||
function removeHashFromString(str) { | ||
return str?.replace("#", ""); | ||
} | ||
function isNotValidInteger(number) { | ||
@@ -29,3 +25,2 @@ return typeof number !== "number" || isNaN(number); | ||
isObject, | ||
removeHashFromString, | ||
}; |
@@ -6,1 +6,3 @@ const parse = require("./lib/parse"); | ||
}; | ||
// TODO: remove (lerna change) |
@@ -18,2 +18,3 @@ const { | ||
fx: "select", | ||
isNested: false, | ||
parameters, | ||
@@ -20,0 +21,0 @@ }); |
const { | ||
convertToOrFormat, | ||
removeHashFromString, | ||
} = require("../helpers/helperfunctions"); | ||
const { | ||
isAnArray, | ||
containsNoErrorFromParser, | ||
isObject, | ||
removeHashFromString, | ||
} = require("../helpers/validation"); | ||
const Operator = Object.freeze({ | ||
EQUALS: "=", | ||
NOT_EQUALS: "<>", | ||
GREATER_THAN: ">", | ||
GREATER_OR_EQUAL: ">=", | ||
LESS_THAN: "<", | ||
LESS_OR_EQUAL: "<=", | ||
LIKE: "LIKE", | ||
IN: "IN", | ||
NOT_IN: "NOT IN", | ||
NOT: "NOT", | ||
AND: "AND", | ||
OR: "OR", | ||
IS_NULL: "IS NULL", | ||
IS_NOT_NULL: "IS NOT NULL", | ||
}); | ||
const objectionFunctions = Object.freeze({ | ||
default: "where", | ||
[Operator.NOT]: "whereNot", | ||
[Operator.NOT_IN]: "whereNotIn", | ||
[Operator.IN]: "whereIn", | ||
[Operator.IS_NULL]: "whereNull", | ||
[Operator.IS_NOT_NULL]: "whereNotNull", | ||
}); | ||
//To reconstruct the parameters to objections format | ||
function parseParametersForObjection(operator, value) { | ||
return Array.isArray(value) | ||
? value.length > 2 | ||
? [removeHashFromString(value[0]), operator, value.slice(1)] | ||
: [removeHashFromString(value[0]), operator, value[1]] | ||
: [removeHashFromString(value), operator]; | ||
function parseParametersForObjection(operator, value, isOr) { | ||
let sequelizeKey, sequelizeOperator, sequelizeValue; | ||
let fx, parameters; | ||
const specialOperators = [ | ||
Operator.IN, | ||
Operator.NOT_IN, | ||
Operator.NOT, | ||
Operator.IS_NULL, | ||
Operator.IS_NOT_NULL, | ||
]; | ||
const isArray = Array.isArray(value); | ||
const isSpecialOperator = specialOperators.some( | ||
(op) => op.toLocaleLowerCase() === operator.toLocaleLowerCase() | ||
); | ||
sequelizeOperator = operator; | ||
if (isArray) { | ||
sequelizeKey = removeHashFromString(value[0]); | ||
if (isSpecialOperator) { | ||
//HANDLE IN AND NOT IN | ||
fx = objectionFunctions[operator]; | ||
sequelizeValue = value.slice(1); | ||
parameters = [sequelizeKey, sequelizeValue]; | ||
} else { | ||
fx = objectionFunctions["default"]; | ||
sequelizeValue = value.length > 2 ? value?.slice(1) : value[1]; | ||
parameters = [sequelizeKey, sequelizeOperator, sequelizeValue]; | ||
} | ||
} else { | ||
//handle NULL AND NOT NULL | ||
sequelizeKey = removeHashFromString(value); | ||
fx = objectionFunctions[operator]; | ||
parameters = [sequelizeKey]; | ||
} | ||
return { | ||
fx: isOr ? convertToOrFormat(fx) : fx, | ||
parameters, | ||
}; | ||
} | ||
//To handle "OR" AND "AND" recursively | ||
function sortArrayFilters(filters, isOr = false) { | ||
function sortNestedFilters(filters, isOr = false) { | ||
let i = 0; | ||
let parsedArray = []; | ||
let errors = []; | ||
filters = isAnArray(filters) ? filters : [filters]; | ||
for (let filter of filters) { | ||
//use the orWhere only on from the second iteration. | ||
//use the orWhere only from the second iteration. | ||
let useOr = isOr && i > 0; | ||
@@ -42,15 +103,32 @@ const parseFilterResponse = parseFilters(filter, [], useOr); | ||
for (let key of keys) { | ||
if (key === "AND" || key === "OR") { | ||
if (isAnArray(filters[key])) { | ||
parsedArray = [ | ||
...parsedArray, | ||
...sortArrayFilters(filters[key], key === "OR"), | ||
]; | ||
} else { | ||
errors.push(`${filters[key]} should be an array`); | ||
} | ||
if ( | ||
key === Operator.AND || | ||
key === Operator.OR || | ||
key === Operator.NOT | ||
) { | ||
const parameters = sortNestedFilters( | ||
filters[key], | ||
key === Operator.OR | ||
); | ||
const fx = | ||
key === Operator.NOT | ||
? objectionFunctions[Operator.NOT] | ||
: objectionFunctions.default; | ||
parsedArray = [ | ||
...parsedArray, | ||
{ | ||
fx: isOr ? convertToOrFormat(fx) : fx, | ||
isNested: true, | ||
parameters, | ||
}, | ||
]; | ||
} else { | ||
const parameters = parseParametersForObjection(key, filters[key]); | ||
const { fx, parameters } = parseParametersForObjection( | ||
key, | ||
filters[key], | ||
isOr | ||
); | ||
parsedArray.push({ | ||
fx: isOr ? "orWhere" : "where", | ||
fx, | ||
isNested: false, | ||
parameters, | ||
@@ -57,0 +135,0 @@ }); |
@@ -16,4 +16,5 @@ const { | ||
parsedArray.push({ | ||
fx: "joinRelated", | ||
parameters: param, | ||
fx: "withGraphFetched", | ||
isNested: false, | ||
parameters: [param], | ||
}); | ||
@@ -20,0 +21,0 @@ } |
@@ -22,2 +22,3 @@ const { | ||
fx: "offset", | ||
isNested: false, | ||
parameters: [offset], | ||
@@ -27,2 +28,3 @@ }); | ||
fx: "limit", | ||
isNested: false, | ||
parameters: [size], | ||
@@ -29,0 +31,0 @@ }); |
@@ -22,2 +22,3 @@ const { | ||
fx: "orderBy", | ||
isNested: false, | ||
parameters: [newSortFields], | ||
@@ -24,0 +25,0 @@ }); |
{ | ||
"name": "@bitovi/objection-querystring-parser", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "", | ||
@@ -9,12 +9,6 @@ "main": "index.js", | ||
}, | ||
"license": "MIT", | ||
"scripts": { | ||
"test": "jest", | ||
"test:watch": "jest --watch", | ||
"lint": "eslint .", | ||
"lint:fix": "eslint --fix .", | ||
"pretty": "prettier --check .", | ||
"pretty:fix": "prettier --write .", | ||
"release:patch": "npm version patch && npm publish --access=public", | ||
"release:minor": "npm version minor && npm publish --access=public", | ||
"release:major": "npm version major && npm publish --access=public" | ||
"test:watch": "jest --watch" | ||
}, | ||
@@ -27,3 +21,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@bitovi/querystring-parser": "^0.6.2" | ||
"@bitovi/querystring-parser": "^0.6.3" | ||
}, | ||
@@ -41,3 +35,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "1592e4ade05eb0a7a54791ecf260430ab21cac0d" | ||
"gitHead": "e114710d17a816f2fc26fe6c4e8cc729762b0dcf" | ||
} |
@@ -21,6 +21,9 @@ ## objection-querystring-parser | ||
- This parser returns an array of results that can be chained together | ||
- Each result is an object that contains an `fx` and a `parameters` key in the format { fx: 'limit', parameters: [10] } | ||
- Each result is an object that contains an `fx`, `isNested` and a `parameters` key in the format { fx: 'limit', isNested: false, parameters: [10] } | ||
- `fx` is the name of the function to be chained to the query | ||
- `parameters` are the parameters to be added to the function, the parameters value is an array that you can spread into your function | ||
- In the format `Query[fx1](...parameters1)[fx2](...parameters2)`. | ||
- `isNested` is a boolean that indicates if a Query is Nested(AND, OR, NOT). | ||
- `parameters` where `isNested` is true is an array of results each with its own `fx`, `isNested` and `parameters`. | ||
- `parameters` where `isNested` is false is an array of parameters to be added to the function `fx`, the parameters value is an array that you would spread into your function `fx`. | ||
- The results are used in the format `Query[fx1](...parameters1)[fx2](...parameters2)`. | ||
- This is better shown with an example [here](https://github.com/bitovi/querystring-parser/tree/main/examples). | ||
@@ -66,2 +69,3 @@ ```js | ||
fx: "offset", | ||
isNested: false, | ||
parameters: [0], | ||
@@ -71,2 +75,3 @@ }, | ||
fx: "limit", | ||
isNested: false, | ||
parameters: [10], | ||
@@ -80,2 +85,24 @@ }, | ||
### Fields Parameters | ||
Reference: [JSON:API - Inclusion of Related Resources](https://jsonapi.org/format/#fetching-sparse-fieldsets) | ||
```js | ||
const result = querystringParser.parse("fields[people]=id,name"); | ||
console.log(result); | ||
{ | ||
orm: "objection", | ||
data: [ | ||
[ | ||
{ | ||
fx: "select", | ||
isNested: false, | ||
parameters: ["id","name"], | ||
}, | ||
], | ||
], | ||
errors: [], | ||
}; | ||
``` | ||
### Include Parameters | ||
@@ -93,3 +120,4 @@ | ||
{ | ||
fx: "select", | ||
fx: "withGraphFetched", | ||
isNested: false, | ||
parameters: ["pets", "dogs"], | ||
@@ -107,3 +135,3 @@ }, | ||
const result = querystringParser.parse( | ||
"filter=or(any('age','10','20'),equals('name','mike'))" | ||
"filter=or(any(age,'10','20'),equals(name,'mike'))" | ||
); | ||
@@ -115,7 +143,41 @@ { | ||
fx: "where", | ||
parameters: ["age", "IN", [10, 20]], | ||
isNested: true, | ||
parameters: [ | ||
{ | ||
fx: "whereIn", | ||
isNested: false, | ||
parameters: ["age", [10, 20]], | ||
}, | ||
{ | ||
fx: "orWhere", | ||
parameters: ["name", "=", "mike"], | ||
}, | ||
], | ||
}, | ||
], | ||
errors: [], | ||
}; | ||
``` | ||
```js | ||
const result = querystringParser.parse( | ||
"filter=not(lessOrEqual(age,'10'),equals(name,null))" | ||
); | ||
{ | ||
orm: "objection", | ||
data: [ | ||
{ | ||
fx: "orWhere", | ||
parameters: ["name", "=", "mike"], | ||
fx: "whereNot", | ||
isNested: true, | ||
parameters: [ | ||
{ | ||
fx: "where", | ||
isNested: false, | ||
parameters: ["age", "<=", 10], | ||
}, | ||
{ | ||
fx: "whereNull", | ||
parameters: ["name"], | ||
}, | ||
], | ||
}, | ||
@@ -127,6 +189,6 @@ ], | ||
** Note: Database Validations should be done before or after passing the query to the library before the database call is made. ** | ||
## Example | ||
- A more practical example on how to use this library in your project can be found [here](https://github.com/bitovi/querystring-parser/tree/main/examples) | ||
### lerna changes (to be removed) |
@@ -52,2 +52,3 @@ const parseFields = require("../lib/parse-fields"); | ||
fx: "select", | ||
isNested: false, | ||
parameters: ["field1", "field2"], | ||
@@ -54,0 +55,0 @@ }, |
@@ -63,2 +63,3 @@ const parseFilter = require("../lib/parse-filter"); | ||
fx: "where", | ||
isNested: false, | ||
parameters: ["name", "=", "michael"], | ||
@@ -72,7 +73,5 @@ }, | ||
{ | ||
title: "should return valid results when using the 'OR' operator", | ||
parameters: [ | ||
{ OR: [{ IN: ["#age", 10, 20] }, { "=": ["#name", "mike"] }] }, | ||
[], | ||
], | ||
title: | ||
"should return valid results for valid parameters for the 'not' operator", | ||
parameters: [{ "=": ["#name", "michael"] }, []], | ||
expectedResults: { | ||
@@ -82,8 +81,5 @@ results: [ | ||
fx: "where", | ||
parameters: ["age", "IN", [10, 20]], | ||
isNested: false, | ||
parameters: ["name", "=", "michael"], | ||
}, | ||
{ | ||
fx: "orWhere", | ||
parameters: ["name", "=", "mike"], | ||
}, | ||
], | ||
@@ -104,7 +100,80 @@ errors: [], | ||
fx: "where", | ||
parameters: ["age", "IN", [10, 20]], | ||
isNested: true, | ||
parameters: [ | ||
{ | ||
fx: "whereIn", | ||
isNested: false, | ||
parameters: ["age", [10, 20]], | ||
}, | ||
{ | ||
fx: "where", | ||
isNested: false, | ||
parameters: ["name", "=", "mike"], | ||
}, | ||
], | ||
}, | ||
], | ||
errors: [], | ||
}, | ||
}, | ||
{ | ||
title: | ||
"should return valid results when using the Nested 'AND' & 'OR' operator", | ||
parameters: [ | ||
{ | ||
AND: [ | ||
{ "=": ["#userType", "Student"] }, | ||
{ | ||
OR: [ | ||
{ "IS NULL": "#house" }, | ||
{ | ||
AND: [{ "=": ["#id", 4] }, { "=": ["#house", "Gryffindor"] }], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
[], | ||
], | ||
expectedResults: { | ||
results: [ | ||
{ | ||
fx: "where", | ||
parameters: ["name", "=", "mike"], | ||
isNested: true, | ||
parameters: [ | ||
{ | ||
fx: "where", | ||
isNested: false, | ||
parameters: ["userType", "=", "Student"], | ||
}, | ||
{ | ||
fx: "where", | ||
isNested: true, | ||
parameters: [ | ||
{ | ||
fx: "whereNull", | ||
isNested: false, | ||
parameters: ["house"], | ||
}, | ||
{ | ||
fx: "orWhere", | ||
isNested: true, | ||
parameters: [ | ||
{ | ||
fx: "where", | ||
isNested: false, | ||
parameters: ["id", "=", 4], | ||
}, | ||
{ | ||
fx: "where", | ||
isNested: false, | ||
parameters: ["house", "=", "Gryffindor"], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
@@ -111,0 +180,0 @@ ], |
@@ -72,2 +72,3 @@ const parsePage = require("../lib/parse-page"); | ||
fx: "offset", | ||
isNested: false, | ||
parameters: [10], | ||
@@ -77,2 +78,3 @@ }, | ||
fx: "limit", | ||
isNested: false, | ||
parameters: [5], | ||
@@ -93,2 +95,3 @@ }, | ||
fx: "offset", | ||
isNested: false, | ||
parameters: [10], | ||
@@ -98,2 +101,3 @@ }, | ||
fx: "limit", | ||
isNested: false, | ||
parameters: [10], | ||
@@ -100,0 +104,0 @@ }, |
@@ -52,2 +52,3 @@ const parseSort = require("../lib/parse-sort"); | ||
fx: "orderBy", | ||
isNested: false, | ||
parameters: [[{ column: "test", order: "ASC" }]], | ||
@@ -54,0 +55,0 @@ }, |
28498
17
840
187