diff --git a/src/paginate.spec.ts b/src/paginate.spec.ts index 5af60ad..bd691b4 100644 --- a/src/paginate.spec.ts +++ b/src/paginate.spec.ts @@ -5,8 +5,8 @@ import { PaginateConfig, FilterOperator, isOperator, - getOperatorFn, getFilterTokens, + OperatorSymbolToFunction, } from './paginate' import { PaginateQuery } from './decorator' import { Entity, PrimaryGeneratedColumn, CreateDateColumn } from 'typeorm' @@ -45,7 +45,7 @@ describe('paginate', () => { repo = connection.getRepository(CatEntity) cats = await repo.save([ repo.create({ name: 'Milo', color: 'brown', age: 6 }), - repo.create({ name: 'Garfield', color: 'ginger', age: null }), + repo.create({ name: 'Garfield', color: 'ginger', age: 5 }), repo.create({ name: 'Shadow', color: 'black', age: 4 }), repo.create({ name: 'George', color: 'white', age: 3 }), repo.create({ name: 'Leche', color: 'white', age: null }), @@ -342,7 +342,7 @@ describe('paginate', () => { const result = await paginate(query, repo, config) - expect(result.data).toStrictEqual([cats[0], cats[2]]) + expect(result.data).toStrictEqual([cats[0], cats[1], cats[2]]) expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.age=$gte:4') }) @@ -356,14 +356,14 @@ describe('paginate', () => { const query: PaginateQuery = { path: '', filter: { - age: '$btw:4,6', + age: '$btw:4,5', }, } const result = await paginate(query, repo, config) - expect(result.data).toStrictEqual([cats[0], cats[2]]) - expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.age=$btw:4,6') + expect(result.data).toStrictEqual([cats[1], cats[2]]) + expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.age=$btw:4,5') }) it('should return result based on is null query', async () => { @@ -382,7 +382,7 @@ describe('paginate', () => { const result = await paginate(query, repo, config) - expect(result.data).toStrictEqual([cats[1], cats[4]]) + expect(result.data).toStrictEqual([cats[4]]) expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.age=$null') }) @@ -402,7 +402,7 @@ describe('paginate', () => { const result = await paginate(query, repo, config) - expect(result.data).toStrictEqual([cats[0], cats[2], cats[3]]) + expect(result.data).toStrictEqual([cats[0], cats[1], cats[2], cats[3]]) expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.age=$not:$null') }) @@ -487,7 +487,7 @@ describe('paginate', () => { { operator: '$btw', name: 'Between' }, { operator: '$not', name: 'Not' }, ])('should get operator function $name for "$operator"', ({ operator, name }) => { - const func = getOperatorFn(operator as FilterOperator) + const func = OperatorSymbolToFunction.get(operator as FilterOperator) expect(func.name).toStrictEqual(name) }) diff --git a/src/paginate.ts b/src/paginate.ts index 26daa98..c495f99 100644 --- a/src/paginate.ts +++ b/src/paginate.ts @@ -72,28 +72,17 @@ export function isOperator(value: unknown): value is FilterOperator { return values(FilterOperator).includes(value as any) } -export function getOperatorFn(op: FilterOperator): (...args: any[]) => FindOperator { - switch (op) { - case FilterOperator.EQ: - return Equal - case FilterOperator.GT: - return MoreThan - case FilterOperator.GTE: - return MoreThanOrEqual - case FilterOperator.IN: - return In - case FilterOperator.NULL: - return IsNull - case FilterOperator.LT: - return LessThan - case FilterOperator.LTE: - return LessThanOrEqual - case FilterOperator.BTW: - return Between - case FilterOperator.NOT: - return Not - } -} +export const OperatorSymbolToFunction = new Map FindOperator>([ + [FilterOperator.EQ, Equal], + [FilterOperator.GT, MoreThan], + [FilterOperator.GTE, MoreThanOrEqual], + [FilterOperator.IN, In], + [FilterOperator.NULL, IsNull], + [FilterOperator.LT, LessThan], + [FilterOperator.LTE, LessThanOrEqual], + [FilterOperator.BTW, Between], + [FilterOperator.NOT, Not], +]) export function getFilterTokens(raw: string): string[] { const tokens = [] @@ -125,12 +114,11 @@ export function getFilterTokens(raw: string): string[] { function parseFilter(query: PaginateQuery, config: PaginateConfig) { const filter = {} - for (const column of Object.keys(query.filter)) { if (!(column in config.filterableColumns)) { continue } - const allowedOperators = config.filterableColumns[column as Column] + const allowedOperators = config.filterableColumns[column] const input = query.filter[column] const statements = !Array.isArray(input) ? [input] : input for (const raw of statements) { @@ -147,12 +135,20 @@ function parseFilter(query: PaginateQuery, config: PaginateConfig) { continue } if (isOperator(op1)) { - const args = op1 === FilterOperator.IN || op1 === FilterOperator.BTW ? value.split(',') : value - filter[column] = - op1 === FilterOperator.BTW ? getOperatorFn(op1)(args[0], args[1]) : getOperatorFn(op1)(args) + switch (op1) { + case FilterOperator.BTW: + filter[column] = OperatorSymbolToFunction.get(op1)(...value.split(',')) + break + case FilterOperator.IN: + filter[column] = OperatorSymbolToFunction.get(op1)(value.split(',')) + break + default: + filter[column] = OperatorSymbolToFunction.get(op1)(value) + break + } } if (isOperator(op2)) { - filter[column] = getOperatorFn(op2)(filter[column]) + filter[column] = OperatorSymbolToFunction.get(op2)(filter[column]) } } } @@ -236,7 +232,7 @@ export async function paginate( } if (query.filter) { - const filter = parseFilter(query, config) + const filter = parseFilter(query, config) queryBuilder.andWhere(new Brackets((qb) => qb.andWhere(filter))) }