@clipboard-health/json-api-nestjs
Version:
TypeScript-friendly utilities for adhering to the JSON:API specification with NestJS.
67 lines • 2.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.queryFilterPreprocessor = queryFilterPreprocessor;
/**
* NestJS-specific query processing based on the output of `ctx.switchToHttp().getRequest().query`.
*
* We handle the following cases:
* 1. For `?filter[age]=10,20`, `value` is `10,20`, which we transform to `{eq: "10,20"}`.
* 2. For `?filter[age]=20`, `value` is `20`, which we transform to `{eq: "20"}`.
* 3. For `?filter[age][gt]=10&filter[age]=20`, `value` may be `[{gt: "10"}, "20"]` or
* `{"20": true, gt: "10"}`, which we transform to `{eq: "20", gt: "10"}`.
* 4. For `?filter[age]=10&filter[age]=20`, `value` is `['10', '20']`, which we transform to `{eq:
* "10,20"}`.
* 5. For `?filter[age][gt]=5&filter[age]=10&filter[age]=20`, `value` is `{'0': '10', '1': '20', gt:
* '5'}`, which we transform to `{eq: "10,20", gt: "5"}`.
*/
function queryFilterPreprocessor(value) {
if (Array.isArray(value)) {
return normalizeArrayFilter(value);
}
if (!isObject(value)) {
// Cases 1 and 2.
return { eq: String(value) };
}
return normalizeObjectFilter(value);
}
function isObject(value) {
return value !== null && value !== undefined && typeof value === "object";
}
function appendFilterValue(filter, key, value) {
return {
...filter,
[key]: filter[key] ? `${filter[key]},${value}` : value,
};
}
function mergeFilters(currentFilter, newFilter) {
return Object.entries(newFilter).reduce((mergedFilter, [key, value]) => appendFilterValue(mergedFilter, key, value), currentFilter);
}
function normalizeArrayFilter(value) {
return value.reduce((filter, filterValue) => {
if (Array.isArray(filterValue)) {
return mergeFilters(filter, normalizeArrayFilter(filterValue));
}
if (isObject(filterValue)) {
return mergeFilters(filter, normalizeObjectFilter(filterValue));
}
return appendFilterValue(filter, "eq", String(filterValue));
}, {});
}
function normalizeObjectFilter(value) {
return Object.entries(value).reduce((filter, [key, filterValue]) => {
if (typeof filterValue === "boolean") {
return appendFilterValue(filter, "eq", key);
}
if (/^\d+$/.test(key)) {
if (Array.isArray(filterValue)) {
return mergeFilters(filter, normalizeArrayFilter(filterValue));
}
if (isObject(filterValue)) {
return mergeFilters(filter, normalizeObjectFilter(filterValue));
}
return appendFilterValue(filter, "eq", String(filterValue));
}
return appendFilterValue(filter, key, Array.isArray(filterValue) ? filterValue.join(",") : String(filterValue));
}, {});
}
//# sourceMappingURL=queryFilterPreprocessor.js.map