From 728b4d363d007ebe49848ae3a365a10139c2191e Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 9 Aug 2024 11:47:16 +0200 Subject: [PATCH] Add removeInvalidFilters utils --- .../server/src/sdk/app/rows/queryUtils.ts | 45 +++++++++ .../src/sdk/app/rows/tests/queryUtils.spec.ts | 96 +++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 packages/server/src/sdk/app/rows/queryUtils.ts create mode 100644 packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts diff --git a/packages/server/src/sdk/app/rows/queryUtils.ts b/packages/server/src/sdk/app/rows/queryUtils.ts new file mode 100644 index 0000000000..84fe05a948 --- /dev/null +++ b/packages/server/src/sdk/app/rows/queryUtils.ts @@ -0,0 +1,45 @@ +import { isLogicalSearchOperator, SearchFilters } from "@budibase/types" +import { cloneDeep } from "lodash/fp" + +export const removeInvalidFilters = ( + filters: SearchFilters, + validFields: string[] +) => { + const result = cloneDeep(filters) + + validFields = validFields.map(f => f.toLowerCase()) + for (const filterKey of Object.keys(result) as (keyof SearchFilters)[]) { + if (typeof result[filterKey] !== "object") { + continue + } + if (isLogicalSearchOperator(filterKey)) { + const resultingConditions: SearchFilters[] = [] + for (const condition of result[filterKey].conditions) { + const resultingCondition = removeInvalidFilters(condition, validFields) + if (Object.keys(resultingCondition).length) { + resultingConditions.push(resultingCondition) + } + } + if (resultingConditions.length) { + result[filterKey].conditions = resultingConditions + } else { + delete result[filterKey] + } + continue + } + + const filter = result[filterKey] + for (const columnKey of Object.keys(filter)) { + if ( + !validFields.map(f => f.toLowerCase()).includes(columnKey.toLowerCase()) + ) { + delete filter[columnKey] + } + } + if (!Object.keys(filter).length) { + delete result[filterKey] + } + } + + return result +} diff --git a/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts b/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts new file mode 100644 index 0000000000..b3852da4c6 --- /dev/null +++ b/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts @@ -0,0 +1,96 @@ +import { SearchFilters } from "@budibase/types" +import { removeInvalidFilters } from "../queryUtils" + +describe("query utils", () => { + describe("removeInvalidFilters", () => { + const fullFilters: SearchFilters = { + equal: { one: "foo" }, + $or: { + conditions: [ + { + equal: { one: "foo2", two: "bar" }, + notEmpty: { one: null }, + $and: { + conditions: [ + { + equal: { three: "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + $and: { + conditions: [{ equal: { one: "foo2" }, notEmpty: { one: null } }], + }, + } + + it("can filter empty queries", () => { + const filters: SearchFilters = {} + const result = removeInvalidFilters(filters, []) + expect(result).toEqual({}) + }) + + it("does not trim any valid field", () => { + const result = removeInvalidFilters(fullFilters, [ + "one", + "two", + "three", + "forth", + ]) + expect(result).toEqual(fullFilters) + }) + + it("trims invalid field", () => { + const result = removeInvalidFilters(fullFilters, [ + "one", + "three", + "forth", + ]) + expect(result).toEqual({ + equal: { one: "foo" }, + $or: { + conditions: [ + { + equal: { one: "foo2" }, + notEmpty: { one: null }, + $and: { + conditions: [ + { + equal: { three: "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + $and: { + conditions: [{ equal: { one: "foo2" }, notEmpty: { one: null } }], + }, + }) + }) + + it("trims invalid field keeping a valid fields", () => { + const result = removeInvalidFilters(fullFilters, ["three", "forth"]) + const expected: SearchFilters = { + $or: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { three: "baz" }, + notEmpty: { forth: null }, + }, + ], + }, + }, + ], + }, + } + expect(result).toEqual(expected) + }) + }) +})