From 23b2e762f8db5a449c43683a71e860d1a677d237 Mon Sep 17 00:00:00 2001 From: Anderson R Date: Thu, 3 Nov 2022 08:20:08 -0300 Subject: [PATCH] feat: added $ilike operator (#373) --- README.md | 2 +- src/paginate.spec.ts | 26 ++++++++++++++++++++++++++ src/paginate.ts | 5 +++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 49fe938..ce052e1 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Pagination and filtering helper method for TypeORM repositories or query builder - Pagination conforms to [JSON:API](https://jsonapi.org/) - Sort by multiple columns - Search across columns -- Filter using operators (`$eq`, `$not`, `$null`, `$in`, `$gt`, `$gte`, `$lt`, `$lte`, `$btw`) +- Filter using operators (`$eq`, `$not`, `$null`, `$in`, `$gt`, `$gte`, `$lt`, `$lte`, `$btw`, `$ilike`) - Include relations ## Installation diff --git a/src/paginate.spec.ts b/src/paginate.spec.ts index 2a09fb1..435a077 100644 --- a/src/paginate.spec.ts +++ b/src/paginate.spec.ts @@ -1146,6 +1146,29 @@ describe('paginate', () => { expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.name=$not:Leche&filter.color=white') }) + it('should return result based on $ilike filter', async () => { + const config: PaginateConfig = { + sortableColumns: ['id'], + filterableColumns: { + name: [FilterOperator.ILIKE], + }, + } + const query: PaginateQuery = { + path: '', + filter: { + name: '$ilike:Garf', + }, + } + + const result = await paginate(query, catRepo, config) + + expect(result.meta.filter).toStrictEqual({ + name: '$ilike:Garf', + }) + expect(result.data).toStrictEqual([cats[1]]) + expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.name=$ilike:Garf') + }) + it('should return result based on filter and search term', async () => { const config: PaginateConfig = { sortableColumns: ['id'], @@ -1338,6 +1361,7 @@ describe('paginate', () => { { operator: '$lte', result: true }, { operator: '$btw', result: true }, { operator: '$not', result: true }, + { operator: '$ilike', result: true }, { operator: '$fake', result: false }, ])('should check operator "$operator" valid is $result', ({ operator, result }) => { expect(isOperator(operator)).toStrictEqual(result) @@ -1353,12 +1377,14 @@ describe('paginate', () => { { operator: '$lte', name: 'LessThanOrEqual' }, { operator: '$btw', name: 'Between' }, { operator: '$not', name: 'Not' }, + { operator: '$ilike', name: 'ILike' }, ])('should get operator function $name for "$operator"', ({ operator, name }) => { const func = OperatorSymbolToFunction.get(operator as FilterOperator) expect(func.name).toStrictEqual(name) }) it.each([ + { string: '$ilike:value', tokens: [null, '$ilike', 'value'] }, { string: '$eq:value', tokens: [null, '$eq', 'value'] }, { string: '$eq:val:ue', tokens: [null, '$eq', 'val:ue'] }, { string: '$in:value1,value2,value3', tokens: [null, '$in', 'value1,value2,value3'] }, diff --git a/src/paginate.ts b/src/paginate.ts index 09aa94f..935feed 100644 --- a/src/paginate.ts +++ b/src/paginate.ts @@ -69,6 +69,7 @@ export enum FilterOperator { LTE = '$lte', BTW = '$btw', NOT = '$not', + ILIKE = '$ilike', } export function isOperator(value: unknown): value is FilterOperator { @@ -85,6 +86,7 @@ export const OperatorSymbolToFunction = new Map(query: PaginateQuery, config: PaginateConfig) { case FilterOperator.IN: filter[column] = OperatorSymbolToFunction.get(op1)(value.split(',')) break + case FilterOperator.ILIKE: + filter[column] = OperatorSymbolToFunction.get(op1)(`%${value}%`) + break default: filter[column] = OperatorSymbolToFunction.get(op1)(value) break