ncrudify
Version:
Configurable CRUD module for NestJS and Mongoose.
181 lines • 7.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryParser = void 0;
class QueryParser {
static parse(queryParams) {
var _a, _b, _c;
const filters = {};
const populate = [];
const sort = {};
let skip = 0;
let limit = 0;
const regexPatterns = {};
for (const [key, value] of Object.entries(queryParams)) {
if (key.endsWith("_op") && typeof value === "string") {
const fieldName = key.replace("_op", "");
if (!regexPatterns[fieldName]) {
regexPatterns[fieldName] = {
cont: [],
isOr: value.toLowerCase() === "or",
};
}
else {
regexPatterns[fieldName].isOr = value.toLowerCase() === "or";
}
continue;
}
if (typeof value === "object" && !Array.isArray(value)) {
const fieldName = key;
if (!regexPatterns[fieldName]) {
regexPatterns[fieldName] = { cont: [], isOr: false };
}
for (const [operator, operatorValue] of Object.entries(value)) {
if (this.operatorsMap[operator]) {
if (["starts", "ends", "cont"].includes(operator) &&
typeof operatorValue === "string") {
if (operator === "starts") {
regexPatterns[fieldName].starts = operatorValue;
}
else if (operator === "ends") {
regexPatterns[fieldName].ends = operatorValue;
}
else if (operator === "cont") {
(_a = regexPatterns[fieldName].cont) === null || _a === void 0 ? void 0 : _a.push(operatorValue);
}
}
else if (operator === "isnull") {
filters[fieldName] = { $exists: false };
}
else if (operator === "notnull") {
filters[fieldName] = { $exists: true };
}
else if (operator === "between" &&
typeof operatorValue === "string") {
const [start, end] = operatorValue
.split(",")
.map((v) => this.castValue(v.trim()));
filters[fieldName] = { $gte: start, $lte: end };
}
else if (operator === "excl" &&
typeof operatorValue === "string") {
filters[fieldName] = {
$not: { $regex: operatorValue, $options: "i" },
};
}
else if (operator === "in" && typeof operatorValue === "string") {
filters[fieldName] = { $in: operatorValue.split(",") };
}
else {
const value = operatorValue == "null" ? null : this.castValue(operatorValue);
const mongoOperator = this.operatorsMap[operator];
if (!filters[fieldName])
filters[fieldName] = {};
filters[fieldName][mongoOperator] = value;
}
}
}
}
else if (key === "populate" && typeof value === "string") {
const paths = value.split(",");
paths.forEach((path) => populate.push({ path }));
}
else if (key === "sort" && typeof value === "string") {
const fields = value.split(",");
for (const field of fields) {
if (field.startsWith("-")) {
sort[field.slice(1)] = -1;
}
else {
sort[field] = 1;
}
}
}
else if (key === "skip" &&
typeof value === "string" &&
!isNaN(Number(value))) {
skip = parseInt(value, 10);
}
else if (key === "limit" &&
typeof value === "string" &&
!isNaN(Number(value))) {
limit = parseInt(value, 10);
}
}
for (const [fieldName, patterns] of Object.entries(regexPatterns)) {
if (patterns.isOr) {
const conditions = [];
if (patterns.starts) {
conditions.push({
[fieldName]: { $regex: `^${patterns.starts}`, $options: "i" },
});
}
if (patterns.ends) {
conditions.push({
[fieldName]: { $regex: `${patterns.ends}$`, $options: "i" },
});
}
(_b = patterns.cont) === null || _b === void 0 ? void 0 : _b.forEach((contPattern) => {
conditions.push({
[fieldName]: { $regex: contPattern, $options: "i" },
});
});
if (conditions.length > 0) {
filters.$or = conditions;
}
}
else {
let pattern = "";
if (patterns.starts) {
pattern += `^${patterns.starts}`;
}
if ((_c = patterns.cont) === null || _c === void 0 ? void 0 : _c.length) {
patterns.cont.forEach((contPattern) => {
pattern += pattern ? `.*${contPattern}` : contPattern;
});
}
if (patterns.ends) {
pattern += pattern ? `.*${patterns.ends}$` : `${patterns.ends}$`;
}
if (pattern) {
filters[fieldName] = { $regex: pattern, $options: "i" };
}
}
}
return { filters, populate, sort, skip, limit };
}
static castValue(value) {
if (typeof value === "string") {
const isoDateRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?([+-]\d{2}:\d{2}|Z)?)?$/;
if (value.match(isoDateRegex)) {
return new Date(value);
}
if (!isNaN(Number(value)))
return Number(value);
if (value === "true")
return true;
if (value === "false")
return false;
return value;
}
return value;
}
}
exports.QueryParser = QueryParser;
QueryParser.operatorsMap = {
eq: "$eq",
ne: "$ne",
gt: "$gt",
gte: "$gte",
lt: "$lt",
lte: "$lte",
starts: "$regex",
ends: "$regex",
cont: "$regex",
excl: "$not",
in: "$in",
notin: "$nin",
isnull: "$exists",
notnull: "$exists",
between: "$gte",
};
//# sourceMappingURL=query-parser.namespace.js.map