@json-api/query-parser
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -7,14 +7,4 @@ "use strict"; | ||
const constraintLists = parser.parse(filterVal, { startRule: "Filter" }); | ||
const toFieldExpression = helpers_1.finalizeFieldExpression(filterOperators); | ||
return constraintLists.map(function toFinalExp(rawExp) { | ||
const exp = toFieldExpression(rawExp); | ||
const finalArgs = filterOperators[exp.operator].finalizeArgs(filterOperators, exp.operator, exp.args.map((arg) => { | ||
if (arg && arg.type === 'RawFieldExpression') { | ||
return toFinalExp(arg); | ||
} | ||
return arg; | ||
})); | ||
return Object.assign({}, exp, { args: finalArgs }); | ||
}); | ||
return constraintLists.map(rawExp => helpers_1.finalizeFieldExpression(filterOperators, rawExp)); | ||
} | ||
exports.default = parse; |
/// <reference types="ramda" /> | ||
import R = require("ramda"); | ||
import { RawFieldExpression } from './parser'; | ||
export declare type Identifier = { | ||
@@ -19,5 +20,17 @@ type: "Identifier"; | ||
}; | ||
export declare type SortField = ({ | ||
field: string; | ||
} | { | ||
expression: FieldExpression; | ||
}) & { | ||
direction: "ASC" | "DESC"; | ||
}; | ||
export declare const isKnownOperator: R.CurriedTypeGuard2<OperatorsConfig, any, Identifier>; | ||
export declare const isBinaryOperator: R.CurriedFunction2<OperatorsConfig, any, boolean>; | ||
export declare const isNaryOperator: R.CurriedFunction2<OperatorsConfig, any, boolean>; | ||
export declare const finalizeFieldExpression: R.CurriedFunction2<OperatorsConfig, any, FieldExpression>; | ||
export declare const toFieldExpression: R.CurriedFunction2<OperatorsConfig, any, FieldExpression>; | ||
export declare function finalizeFieldExpression(operators: OperatorsConfig, it: RawFieldExpression): { | ||
args: any[]; | ||
type: "FieldExpression"; | ||
operator: string; | ||
}; |
@@ -14,3 +14,3 @@ "use strict"; | ||
}); | ||
exports.finalizeFieldExpression = R.curry((operators, it) => { | ||
exports.toFieldExpression = R.curry((operators, it) => { | ||
if (!(it && it.type === "RawFieldExpression")) { | ||
@@ -52,3 +52,14 @@ throw new SyntaxError("Expected a parenthesized list."); | ||
"or must be a two-item list without any operators (in which case the " + | ||
"`eq` operator is inferred)."); | ||
"`eq` operator is inferred, if it's supported)."); | ||
}); | ||
function finalizeFieldExpression(operators, it) { | ||
const finalizedExp = exports.toFieldExpression(operators, it); | ||
const finalArgs = operators[finalizedExp.operator].finalizeArgs(operators, finalizedExp.operator, finalizedExp.args.map((arg) => { | ||
if (arg && arg.type === 'RawFieldExpression') { | ||
return finalizeFieldExpression(operators, arg); | ||
} | ||
return arg; | ||
})); | ||
return Object.assign({}, finalizedExp, { args: finalArgs }); | ||
} | ||
exports.finalizeFieldExpression = finalizeFieldExpression; |
declare namespace Parser { | ||
export type Identifier = { type: "identifier", value: string }; | ||
export type Atom = number | string | boolean | null | Identifier; | ||
export type Value = Atom | List; | ||
export type Value = Atom | List | RawFieldExpression; | ||
@@ -10,8 +10,13 @@ // List is an interface as a hack for it being recursive. | ||
interface RawFieldExpression { | ||
type: "RawFieldExpression", | ||
items: Value[] | ||
} | ||
// The parse for sort fields has a raw List in the expression field, | ||
// as we have no contextual info to convert it to anything else. | ||
export type SortField = ({ | ||
export type RawSortField = ({ | ||
field: string | ||
} | { | ||
expression: List | ||
expression: RawFieldExpression | ||
}) & { | ||
@@ -21,6 +26,6 @@ direction: "ASC" | "DESC" | ||
export function parse(input: string, opts: { startRule: "Sort" }): SortField[] | ||
export function parse(input: string, opts: { startRule: "Filter" }): List[] | ||
export function parse(input: string, opts: { startRule: "Sort" }): RawSortField[] | ||
export function parse(input: string, opts: { startRule: "Filter" }): RawFieldExpression[] | ||
} | ||
export = Parser; |
@@ -5,3 +5,3 @@ "use strict"; | ||
const helpers_1 = require("../src/helpers"); | ||
const helpers_2 = require("./helpers"); | ||
const utils_1 = require("./utils"); | ||
const filter_param_parser_1 = require("../src/filter-param-parser"); | ||
@@ -96,5 +96,5 @@ const noValidationFinalizeArgs = function (a, b, args) { | ||
}); | ||
it("should treat as a no-arg expression if the arg is known + n-ary", () => { | ||
it("should treat as an expression with an empty arg list if the operator is known + n-ary", () => { | ||
expect(filter_param_parser_1.default(nowOperator, "(now)")).to.deep.equal([ | ||
helpers_2.FieldExpression("now", []) | ||
utils_1.FieldExpression("now", []) | ||
]); | ||
@@ -106,3 +106,3 @@ }); | ||
expect(filter_param_parser_1.default(nowOperator, "(now,1)")).to.deep.equal([ | ||
helpers_2.FieldExpression("now", [1]) | ||
utils_1.FieldExpression("now", [1]) | ||
]); | ||
@@ -112,3 +112,3 @@ }); | ||
expect(filter_param_parser_1.default(eqOperator, "(fieldName,1)")).to.deep.equal([ | ||
helpers_2.FieldExpression("eq", [helpers_2.Identifier("fieldName"), 1]) | ||
utils_1.FieldExpression("eq", [utils_1.Identifier("fieldName"), 1]) | ||
]); | ||
@@ -129,6 +129,6 @@ }); | ||
expect(filter_param_parser_1.default(eqOperator, "(fieldName,eq,1)")).to.deep.equal([ | ||
helpers_2.FieldExpression("eq", [{ type: "Identifier", value: "fieldName" }, 1]) | ||
utils_1.FieldExpression("eq", [{ type: "Identifier", value: "fieldName" }, 1]) | ||
]); | ||
expect(filter_param_parser_1.default(gteOperator, "(fieldName,gte,1)")).to.deep.equal([ | ||
helpers_2.FieldExpression("gte", [{ type: "Identifier", value: "fieldName" }, 1]) | ||
utils_1.FieldExpression("gte", [{ type: "Identifier", value: "fieldName" }, 1]) | ||
]); | ||
@@ -139,3 +139,3 @@ }); | ||
expect(filter_param_parser_1.default(gteOperator, "(gte,gte,1)")).to.deep.equal([ | ||
helpers_2.FieldExpression("gte", [{ type: "Identifier", value: "gte" }, 1]) | ||
utils_1.FieldExpression("gte", [{ type: "Identifier", value: "gte" }, 1]) | ||
]); | ||
@@ -145,3 +145,3 @@ }); | ||
expect(filter_param_parser_1.default(nowOperator, "(now,fieldName,[])")).to.deep.equal([ | ||
helpers_2.FieldExpression("now", [helpers_2.Identifier("fieldName"), []]) | ||
utils_1.FieldExpression("now", [utils_1.Identifier("fieldName"), []]) | ||
]); | ||
@@ -152,3 +152,3 @@ }); | ||
.to.deep.equal([ | ||
helpers_2.FieldExpression("gte", [helpers_2.Identifier("now"), [2]]) | ||
utils_1.FieldExpression("gte", [utils_1.Identifier("now"), [2]]) | ||
]); | ||
@@ -171,13 +171,21 @@ }); | ||
expect(filter_param_parser_1.default(nowOperator, "(now,233,fieldName,(now),[true])")).to.deep.equal([ | ||
helpers_2.FieldExpression("now", [233, helpers_2.Identifier("fieldName"), helpers_2.FieldExpression("now", []), [true]]) | ||
utils_1.FieldExpression("now", [233, utils_1.Identifier("fieldName"), utils_1.FieldExpression("now", []), [true]]) | ||
]); | ||
}); | ||
}); | ||
describe("multiple constraints", () => { | ||
it("should support them, one listed directly after the other", () => { | ||
expect(filter_param_parser_1.default(withFieldOperators, "(a,lte,1)(a,4)")).to.deep.equal([ | ||
utils_1.FieldExpression("lte", [utils_1.Identifier("a"), 1]), | ||
utils_1.FieldExpression("eq", [utils_1.Identifier("a"), 4]) | ||
]); | ||
}); | ||
}); | ||
describe("finalizeArgs", () => { | ||
it("should call it recursively", () => { | ||
expect(filter_param_parser_1.default(gteExtendedOperator, "(gte,1000,fieldName,230)")).to.deep.equal([ | ||
helpers_2.FieldExpression("gte", ["custom args"]) | ||
utils_1.FieldExpression("gte", ["custom args"]) | ||
]); | ||
expect(filter_param_parser_1.default(Object.assign({}, andOrOperators, gteExtendedOperator), "(and,(gte,1000,fieldName,230))")).to.deep.equal([ | ||
helpers_2.FieldExpression("and", [helpers_2.FieldExpression("gte", ["custom args"])]) | ||
utils_1.FieldExpression("and", [utils_1.FieldExpression("gte", ["custom args"])]) | ||
]); | ||
@@ -187,3 +195,3 @@ expect(() => filter_param_parser_1.default(nowProperOperator, "(now,1)")) | ||
expect(filter_param_parser_1.default(nowProperOperator, "(now)")).to.deep.equal([ | ||
helpers_2.FieldExpression("now", []) | ||
utils_1.FieldExpression("now", []) | ||
]); | ||
@@ -216,15 +224,15 @@ const missingFieldError = /field reference required/; | ||
.to.deep.equal([ | ||
helpers_2.FieldExpression("and", [ | ||
helpers_2.FieldExpression("eq", [{ type: "Identifier", value: "field" }, 2]), | ||
helpers_2.FieldExpression("gte", [helpers_2.Identifier("date"), helpers_2.FieldExpression("now", [])]), | ||
helpers_2.FieldExpression("eq", [{ type: "Identifier", value: "test" }, 4]) | ||
utils_1.FieldExpression("and", [ | ||
utils_1.FieldExpression("eq", [{ type: "Identifier", value: "field" }, 2]), | ||
utils_1.FieldExpression("gte", [utils_1.Identifier("date"), utils_1.FieldExpression("now", [])]), | ||
utils_1.FieldExpression("eq", [{ type: "Identifier", value: "test" }, 4]) | ||
]) | ||
]); | ||
expect(sutWithOps("(and,true)")).to.deep.equal([ | ||
helpers_2.FieldExpression("and", [true]) | ||
utils_1.FieldExpression("and", [true]) | ||
]); | ||
expect(filter_param_parser_1.default(withFieldOperators, "(test,lte,(a,eq,c))")).to.deep.equal([ | ||
helpers_2.FieldExpression("lte", [ | ||
helpers_2.Identifier("test"), | ||
helpers_2.FieldExpression("eq", [helpers_2.Identifier("a"), helpers_2.Identifier("c")]) | ||
utils_1.FieldExpression("lte", [ | ||
utils_1.Identifier("test"), | ||
utils_1.FieldExpression("eq", [utils_1.Identifier("a"), utils_1.Identifier("c")]) | ||
]) | ||
@@ -234,8 +242,8 @@ ]); | ||
.to.deep.equal([ | ||
helpers_2.FieldExpression("and", [ | ||
helpers_2.FieldExpression("or", [ | ||
helpers_2.FieldExpression("and", [ | ||
helpers_2.FieldExpression("eq", [helpers_2.Identifier("it"), 3]) | ||
utils_1.FieldExpression("and", [ | ||
utils_1.FieldExpression("or", [ | ||
utils_1.FieldExpression("and", [ | ||
utils_1.FieldExpression("eq", [utils_1.Identifier("it"), 3]) | ||
]), | ||
helpers_2.FieldExpression("gte", [helpers_2.Identifier("test"), null]) | ||
utils_1.FieldExpression("gte", [utils_1.Identifier("test"), null]) | ||
]) | ||
@@ -242,0 +250,0 @@ ]) |
@@ -5,3 +5,3 @@ "use strict"; | ||
const sut = require("../src/parser"); | ||
const helpers_1 = require("./helpers"); | ||
const utils_1 = require("./utils"); | ||
const parseFilter = (str) => sut.parse(str, { startRule: "Filter" }); | ||
@@ -18,4 +18,4 @@ const parseSort = (str) => sut.parse(str, { startRule: "Sort" }); | ||
expect(parseFilter("(ab,c)(3,e)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([helpers_1.Identifier("ab"), helpers_1.Identifier("c")]), | ||
helpers_1.RawFieldExpression([3, helpers_1.Identifier("e")]) | ||
utils_1.RawFieldExpression([utils_1.Identifier("ab"), utils_1.Identifier("c")]), | ||
utils_1.RawFieldExpression([3, utils_1.Identifier("e")]) | ||
]); | ||
@@ -66,5 +66,5 @@ expect(() => parseFilter("(ab,c),(3,e)")).to.throw(/but "," found/); | ||
items: [ | ||
helpers_1.Identifier("x"), | ||
helpers_1.Identifier("y"), | ||
helpers_1.Identifier("z") | ||
utils_1.Identifier("x"), | ||
utils_1.Identifier("y"), | ||
utils_1.Identifier("z") | ||
] | ||
@@ -92,3 +92,3 @@ }; | ||
expect(sut.parse("(true,truedat)", { startRule: "Filter" })) | ||
.to.deep.equal([helpers_1.RawFieldExpression([true, helpers_1.Identifier("truedat")])]); | ||
.to.deep.equal([utils_1.RawFieldExpression([true, utils_1.Identifier("truedat")])]); | ||
}); | ||
@@ -113,15 +113,15 @@ it("may not have a quotation mark in it", () => { | ||
expect(parseFilter("(a-test)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([helpers_1.Identifier("a-test")]) | ||
utils_1.RawFieldExpression([utils_1.Identifier("a-test")]) | ||
]); | ||
expect(parseFilter("(a-22d)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([helpers_1.Identifier("a-22d")]) | ||
utils_1.RawFieldExpression([utils_1.Identifier("a-22d")]) | ||
]); | ||
expect(parseFilter("(a1d)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([helpers_1.Identifier("a1d")]) | ||
utils_1.RawFieldExpression([utils_1.Identifier("a1d")]) | ||
]); | ||
expect(parseFilter("(a.test)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([helpers_1.Identifier("a.test")]) | ||
utils_1.RawFieldExpression([utils_1.Identifier("a.test")]) | ||
]); | ||
expect(parseFilter("(a.22d)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([helpers_1.Identifier("a.22d")]) | ||
utils_1.RawFieldExpression([utils_1.Identifier("a.22d")]) | ||
]); | ||
@@ -138,12 +138,12 @@ }); | ||
expect(parseFilter("(2)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([2]) | ||
utils_1.RawFieldExpression([2]) | ||
]); | ||
expect(parseFilter("(-2)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([-2]) | ||
utils_1.RawFieldExpression([-2]) | ||
]); | ||
expect(parseFilter("(2.1)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([2.1]) | ||
utils_1.RawFieldExpression([2.1]) | ||
]); | ||
expect(parseFilter("(-2.1)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([-2.1]) | ||
utils_1.RawFieldExpression([-2.1]) | ||
]); | ||
@@ -153,6 +153,6 @@ }); | ||
expect(parseFilter("(.99)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([.99]) | ||
utils_1.RawFieldExpression([.99]) | ||
]); | ||
expect(parseFilter("(-.99)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([-0.99]) | ||
utils_1.RawFieldExpression([-0.99]) | ||
]); | ||
@@ -170,9 +170,9 @@ }); | ||
expect(parseFilter("(0.99)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([.99]) | ||
utils_1.RawFieldExpression([.99]) | ||
]); | ||
expect(parseFilter("(011.99)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([11.99]) | ||
utils_1.RawFieldExpression([11.99]) | ||
]); | ||
expect(parseFilter("(001.99)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([1.99]) | ||
utils_1.RawFieldExpression([1.99]) | ||
]); | ||
@@ -184,3 +184,3 @@ }); | ||
expect(parseFilter("(`test`,!test2!)")) | ||
.to.deep.equal([helpers_1.RawFieldExpression(['test', 'test2'])]); | ||
.to.deep.equal([utils_1.RawFieldExpression(['test', 'test2'])]); | ||
}); | ||
@@ -191,3 +191,3 @@ }); | ||
expect(parseFilter("(true,false,null)")).to.deep.equal([ | ||
helpers_1.RawFieldExpression([true, false, null]) | ||
utils_1.RawFieldExpression([true, false, null]) | ||
]); | ||
@@ -194,0 +194,0 @@ }); |
{ | ||
"name": "@json-api/query-parser", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "A query parser for the ?filter and ?sort param syntax used by @json-api/server", | ||
@@ -5,0 +5,0 @@ "main": "build/src/index.js", |
65498
19
1841