From da065985032a7e02cd07a843e0703a1446505b03 Mon Sep 17 00:00:00 2001 From: Akhil Reddy Date: Fri, 31 Jan 2025 11:12:51 +0530 Subject: [PATCH] updated filter parser --- src/pagination.ts | 12 +---- src/utils/queryParser.ts | 106 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 src/utils/queryParser.ts diff --git a/src/pagination.ts b/src/pagination.ts index 1ff21d1..bb9165c 100644 --- a/src/pagination.ts +++ b/src/pagination.ts @@ -1,4 +1,5 @@ import { z } from "zod"; +import { parse } from "./utils/queryParser"; export const pageMetadata = z.object({ count: z.number(), @@ -43,16 +44,7 @@ export function getFilterObject( const filterObj: Array<{}> = []; if (params.filter && params.filter != "") { - const filterOptions = params.filter.split(","); - filterOptions.forEach((item) => { - if (item.includes("!=")) { - const [key, val] = item.split("!=").map((token) => token.trim()); - if (validFields.includes(key)) filterObj.push({ [key]: { $ne: val } }); - } else if (item.includes("=")) { - const [key, val] = item.split("=").map((token) => token.trim()); - if (validFields.includes(key)) filterObj.push({ [key]: { $eq: val } }); - } - }); + filterObj.push(...parse(params.filter, validFields)); } return filterObj; diff --git a/src/utils/queryParser.ts b/src/utils/queryParser.ts new file mode 100644 index 0000000..76549d5 --- /dev/null +++ b/src/utils/queryParser.ts @@ -0,0 +1,106 @@ +import mongoose from "mongoose"; + +type ParsedQuery = Array< + Record< + string, + Record<"$eq" | "$neq" | "$in" | "$nin", string | Date | Object> + > +>; + +function convertValue(value: any) { + if (mongoose.Types.ObjectId.isValid(value)) { + return mongoose.Types.ObjectId.createFromHexString(value); + } else if (!isNaN(Date.parse(value))) { + return new Date(value); + } else { + return value; + } +} + +export function parse(query: string, validFields: Array): ParsedQuery { + const result = []; + + let currentStage = "field"; + let token = ""; + let field = ""; + let op = ""; + let value = ""; + let valueArr = []; + for (let i = 0; i < query.length; i++) { + let char = query[i]; + + if (currentStage === "field") { + if (char === "=" || char === "!") { + field = token; + token = ""; + currentStage = "value"; + + if (char === "=") { + op = "$eq"; + } else { + op = "$neq"; + i++; + } + + continue; + } + + token += char; + } + + if (currentStage === "value") { + if (char === "[") { + currentStage = "valueArr"; + continue; + } + + if (char === "," || i == query.length - 1) { + if (i == query.length - 1) token += char; + + value = token; + if (validFields.includes(field)) + result.push({ [field]: { [op]: convertValue(value) } }); + + token = ""; + field = ""; + op = ""; + + currentStage = "field"; + + continue; + } + + token += char; + } + + if (currentStage === "valueArr") { + if (char === ",") { + valueArr.push(convertValue(token)); + token = ""; + continue; + } + + if (char === "]") { + valueArr.push(token); + if (validFields.includes(field)) + result.push({ + [field]: { [op === "$eq" ? "$in" : "$nin"]: valueArr }, + }); + + token = ""; + field = ""; + op = ""; + valueArr = []; + + currentStage = "field"; + i++; + + continue; + } + + token += char; + } + } + + return result; +}