Files
permit-api/src/utils/queryParser.ts
2025-06-18 10:58:02 +05:30

93 lines
2.8 KiB
TypeScript

import mongoose from "mongoose";
type MongoFilter = Record<string, any>;
function convertValue(value: string) {
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
return new Date(value);
} else if (!isNaN(Number(value))) {
return Number(value);
} else if (mongoose.Types.ObjectId.isValid(value)) {
return new mongoose.Types.ObjectId(value);
} else if (value === "true") {
return true;
} else if (value === "false") {
return false;
} else if (value === "null") {
return null;
}
return value;
}
function formulaToMongoFilter(formula: string): MongoFilter {
// Check for array syntax first (values in parentheses)
const arrayMatch = formula.match(/([^!<>=]+)([!<>=]*)=\(([^)]+)\)/);
if (arrayMatch) {
const [, field, operator, values] = arrayMatch;
const trimmedField = field.trim();
if (trimmedField === "tenantId") return {};
// Split values by comma and trim each value
const valueArray = values
.split(",")
.map((v) => v.trim().replace(/^['"]|['"]$/g, ""));
// Convert each value to appropriate type
const parsedValues = valueArray.map((value) => convertValue(value));
// If no operator or equals operator, use $in
if (!operator || operator === "=") {
return { [trimmedField]: { $in: parsedValues } };
}
// If not equals operator, use $nin
else if (operator === "!") {
return { [trimmedField]: { $nin: parsedValues } };
}
// Other operators don't make sense with arrays
throw new Error(`Unsupported operator with array values: ${operator}`);
}
// Original single value processing
const operatorMatch = formula.match(/([^!<>=]+)([!<>=]+)(.+)/);
if (!operatorMatch) {
throw new Error(`Invalid formula format: ${formula}`);
}
const [, field, operator, value] = operatorMatch;
const trimmedField = field.trim();
const trimmedValue = value.trim().replace(/^['"]|['"]$/g, "");
if (trimmedField === "tenantId") return {};
// Convert value to appropriate type (date or number if possible)
let parsedValue: any = convertValue(trimmedValue);
// Convert operator to MongoDB operator
switch (operator) {
case "=":
return { [trimmedField]: { $eq: parsedValue } };
case "!=":
return { [trimmedField]: { $ne: parsedValue } };
case ">":
return { [trimmedField]: { $gt: parsedValue } };
case "<":
return { [trimmedField]: { $lt: parsedValue } };
case ">=":
return { [trimmedField]: { $gte: parsedValue } };
case "<=":
return { [trimmedField]: { $lte: parsedValue } };
default:
throw new Error(`Unsupported operator: ${operator}`);
}
}
export function parse(formulas: string[]): Array<MongoFilter> {
const parsedQuery: Array<MongoFilter> = formulas.map((formula) =>
formulaToMongoFilter(formula)
);
return parsedQuery;
}