diff --git a/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/__tests__/add-default-conjunction.util.spec.ts b/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/__tests__/add-default-conjunction.util.spec.ts index e1a2c69af19..6481b20a252 100644 --- a/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/__tests__/add-default-conjunction.util.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/__tests__/add-default-conjunction.util.spec.ts @@ -12,4 +12,24 @@ describe('addDefaultConjunctionIfMissing', () => { 'and(field[eq]:1)', ); }); + + it('should add default conjunction when a bare filter is mixed with a nested conjunction', () => { + expect( + addDefaultConjunctionIfMissing( + "status[eq]:'TODO',and(title[ilike]:'%test%')", + ), + ).toEqual("and(status[eq]:'TODO',and(title[ilike]:'%test%'))"); + }); + + it('should not add default conjunction for root or conjunction', () => { + expect(addDefaultConjunctionIfMissing('or(field[eq]:1)')).toEqual( + 'or(field[eq]:1)', + ); + }); + + it('should not add default conjunction for root not conjunction', () => { + expect(addDefaultConjunctionIfMissing('not(field[eq]:1)')).toEqual( + 'not(field[eq]:1)', + ); + }); }); diff --git a/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/add-default-conjunction.util.ts b/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/add-default-conjunction.util.ts index 8fde997cd91..83c7cc0efb7 100644 --- a/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/add-default-conjunction.util.ts +++ b/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/add-default-conjunction.util.ts @@ -1,9 +1,12 @@ -import { Conjunctions } from 'src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter.util'; +import { + Conjunctions, + ROOT_FILTER_CONJUNCTION_REGEX, +} from 'src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter.util'; export const DEFAULT_CONJUNCTION = Conjunctions.and; export const addDefaultConjunctionIfMissing = (filterQuery: string): string => { - if (!(filterQuery.includes('(') && filterQuery.includes(')'))) { + if (!ROOT_FILTER_CONJUNCTION_REGEX.test(filterQuery)) { return `${DEFAULT_CONJUNCTION}(${filterQuery})`; } diff --git a/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter.util.ts b/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter.util.ts index 0b8fd3dd15f..82c5221971d 100644 --- a/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter.util.ts +++ b/packages/twenty-server/src/engine/api/rest/input-request-parsers/filter-parser-utils/parse-filter.util.ts @@ -17,13 +17,15 @@ export enum Conjunctions { not = 'not', } +export const ROOT_FILTER_CONJUNCTION_REGEX = new RegExp( + `^(${Object.values(Conjunctions).join('|')})\\((.+)\\)$`, +); + export const parseFilter = ( filterQuery: string, ): Record => { const result = {}; - const match = filterQuery.match( - `^(${Object.values(Conjunctions).join('|')})\\((.+)\\)$`, - ); + const match = filterQuery.match(ROOT_FILTER_CONJUNCTION_REGEX); if (match) { const conjunction = match?.[1];