import { CompositeFilterDescriptor, FilterDescriptor, isCompositeFilterDescriptor } from './filtering/filter-descriptor.interface'; import { compose, ifElse } from './funcs'; import { normalizeField, quote, toLower, isDateValue, isStringValue, serializeFilters, encodeValue, Transformation, toUTC } from './filter-serialization.common'; import { ODataSettings } from './odata.operators'; import { normalizeFilters } from './filtering/filter.operators'; const formatDate: (settings: any) => Transformation = ({ utcDates }: ODataSettings) => ({ field, value, ignoreCase, operator }) => ({ value: JSON.stringify(!utcDates ? toUTC(value) : value).replace(/"/g, ""), field, ignoreCase, operator }); const fnFormatter = ({ operator }) => ({ field, value }: FilterDescriptor): string => `${operator}(${field},${value})`; const singleOperatorFormatter = ({ operator }) => ({ field, value }: FilterDescriptor): string => `${field} ${operator} ${value}`; const stringFormat = formatter => compose(formatter, encodeValue, quote, toLower, normalizeField); const stringFnOperator = settings => stringFormat(fnFormatter(settings)); const stringOperator = settings => stringFormat(singleOperatorFormatter(settings)); const numericOperator = settings => compose(singleOperatorFormatter(settings), normalizeField); const dateOperator = settings => compose( singleOperatorFormatter(settings), normalizeField, formatDate(settings) ); const ifDate = settings => ifElse(isDateValue, dateOperator(settings), numericOperator(settings)); const typedOperator = settings => ifElse(isStringValue, stringOperator(settings), ifDate(settings)); const appendEqual = str => `${str} eq -1`; const nonValueExpression = formatter => compose(formatter, normalizeField); const filterOperators = (operator: string, settings: ODataSettings) => ({ contains: stringFnOperator({ ...settings, operator: "contains" }), doesnotcontain: compose(appendEqual, stringFnOperator({ ...settings, operator: "indexof" })), endswith: stringFnOperator({ ...settings, operator: "endswith" }), eq: typedOperator({ ...settings, operator: "eq" }), gt: typedOperator({ ...settings, operator: "gt" }), gte: typedOperator({ ...settings, operator: "ge" }), isempty: nonValueExpression(({ field }: FilterDescriptor): string => `${field} eq ''`), isnotempty: nonValueExpression(({ field }: FilterDescriptor): string => `${field} ne ''`), isnotnull: nonValueExpression(({ field }: FilterDescriptor): string => `${field} ne null`), isnull: nonValueExpression(({ field }: FilterDescriptor): string => `${field} eq null`), lt: typedOperator({ ...settings, operator: "lt" }), lte: typedOperator({ ...settings, operator: "le" }), neq: typedOperator({ ...settings, operator: "ne" }), startswith: stringFnOperator({ ...settings, operator: "startswith" }) }[operator]); const join = x => ` ${x.logic} `; const serialize = settings => x => filterOperators(x.operator, settings)(x); const serializeAll = settings => serializeFilters( filter => ifElse(isCompositeFilterDescriptor, serializeAll(settings), serialize(settings))(filter), join ); /** * @hidden */ export const serializeFilter = (filter: CompositeFilterDescriptor, settings: any = {}): string => { if (filter.filters && filter.filters.length) { return "$filter=" + serializeAll(settings)(normalizeFilters(filter)); } return ""; };