From 8011232e9cf5bd2d4ccb5c95b5ef90f172787b85 Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Wed, 17 Jun 2020 17:13:33 -0400 Subject: [PATCH] Rough in filter param --- src/middleware/sanitize-query.ts | 19 ++++++++++++- src/services/items.ts | 46 ++++++++++++++++++++++++++++++++ src/types/query.ts | 9 +++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/middleware/sanitize-query.ts b/src/middleware/sanitize-query.ts index 1111cb4f12..5d3474e411 100644 --- a/src/middleware/sanitize-query.ts +++ b/src/middleware/sanitize-query.ts @@ -4,7 +4,7 @@ */ import { RequestHandler } from 'express'; -import { Query, Sort } from '../types/query'; +import { Query, Sort, Filter, FilterOperator } from '../types/query'; const sanitizeQuery: RequestHandler = (req, res, next) => { if (!req.query) return; @@ -19,6 +19,10 @@ const sanitizeQuery: RequestHandler = (req, res, next) => { query.sort = sanitizeSort(req.query.sort); } + if (req.query.filter) { + query.filter = sanitizeFilter(req.query.filter); + } + res.locals.query = query; return next(); }; @@ -46,3 +50,16 @@ function sanitizeSort(rawSort: any) { return { column, order } as Sort; }); } + +function sanitizeFilter(rawFilter: any) { + const filters: Filter[] = []; + + Object.keys(rawFilter).forEach((column) => { + Object.keys(rawFilter[column]).forEach((operator: FilterOperator) => { + const value = rawFilter[column][operator]; + filters.push({ column, operator, value }); + }); + }); + + return filters; +} diff --git a/src/services/items.ts b/src/services/items.ts index 5a2fc28afb..65e3bf68fd 100644 --- a/src/services/items.ts +++ b/src/services/items.ts @@ -16,16 +16,62 @@ export const readItems = async (collection: string, query: Query = {}) => { dbQuery.orderBy(query.sort); } + if (query.filter) { + query.filter.forEach((filter) => { + if (filter.operator === 'eq') { + dbQuery.where({ [filter.column]: filter.value }); + } + + if (filter.operator === 'neq') { + dbQuery.whereNot({ [filter.column]: filter.value }); + } + + if (filter.operator === 'null') { + dbQuery.whereNull(filter.column); + } + + if (filter.operator === 'nnull') { + dbQuery.whereNotNull(filter.column); + } + }); + } + return await dbQuery; }; export const readItem = async (collection: string, pk: number | string, query: Query = {}) => { const dbQuery = database.select('*').from(collection).where({ id: pk }); + /** + * @TODO + * Merge query building between items / item. It should be the same for both, with the exception + * of limit / page etc + */ + if (query.sort) { dbQuery.orderBy(query.sort); } + if (query.filter) { + query.filter.forEach((filter) => { + if (filter.operator === 'eq') { + dbQuery.where({ [filter.column]: filter.value }); + } + + if (filter.operator === 'neq') { + dbQuery.whereNot({ [filter.column]: filter.value }); + } + + if (filter.operator === 'null') { + dbQuery.whereNull(filter.column); + } + + if (filter.operator === 'nnull') { + dbQuery.whereNotNull(filter.column); + } + }); + } + const records = await dbQuery; return records[0]; diff --git a/src/types/query.ts b/src/types/query.ts index d3cbf4ceea..89a7b3a4ed 100644 --- a/src/types/query.ts +++ b/src/types/query.ts @@ -1,9 +1,18 @@ export type Query = { fields?: string[]; sort?: Sort[]; + filter?: Filter[]; }; export type Sort = { column: string; order: 'asc' | 'desc'; }; + +export type Filter = { + column: string; + operator: FilterOperator; + value: null | string | number; +}; + +export type FilterOperator = 'eq' | 'neq' | 'in' | 'nin' | 'null' | 'nnull';