import { isArray, isNonEmptyString, isNumber, isObject, isString, } from '@sniptt/guards'; import { GraphQLVariables } from 'msw'; import { isDefined } from 'twenty-shared/utils'; type StringFilter = { equals?: string; contains?: string; in?: Array; notIn?: Array; }; const filterData = ( data: Array, where: Record, ): Array => data.filter((item) => { // { firstName: {contains: '%string%' }} // { lastName: {equals: 'string' }} // { is: { company: { equals: 'string' }}} let isMatch: boolean = ( Object.keys(where) as Array ).every((key) => { if (!['OR', 'AND', 'NOT'].includes(key)) { const filterElement = where[key] as StringFilter & { is?: object }; if (isDefined(filterElement.is)) { const nestedKey = Object.keys(filterElement.is)[0] as string; if ( item[key as keyof typeof item] && isObject(item[key as keyof typeof item]) ) { const nestedItem = item[key as keyof typeof item]; return ( nestedItem[nestedKey as keyof typeof nestedItem] === ( filterElement.is[ nestedKey as keyof typeof filterElement.is ] as StringFilter ).equals ); } } if (isNonEmptyString(filterElement.equals)) { return item[key as keyof typeof item] === filterElement.equals; } if (isNonEmptyString(filterElement.contains)) { return (item[key as keyof typeof item] as string) .toLocaleLowerCase() .includes( filterElement.contains.replaceAll('%', '').toLocaleLowerCase(), ); } if (isArray(filterElement.in)) { const itemValue = item[key as keyof typeof item] as string; return filterElement.in.includes(itemValue); } if (isArray(filterElement.notIn)) { const itemValue = item[key as keyof typeof item] as string; if (filterElement.notIn.length === 0) return true; return !filterElement.notIn.includes(itemValue); } } return false; }); // { OR: [{ firstName: filter }, { lastName: filter }] if (isArray(where.OR)) { isMatch = isMatch || where.OR.some((orFilter: any) => filterData(data, orFilter).includes(item), ); } if (isArray(where.AND)) { isMatch = isMatch || where.AND.every((andFilter: any) => filterData(data, andFilter).includes(item), ); } return isMatch; }); export const filterAndSortData = ( data: Array, where?: Record, orderBy?: Array, limit?: number, ): Array => { let filteredData = data; if (isDefined(where)) { filteredData = filterData(data, where); } if (isArray(orderBy) && orderBy.length > 0 && isDefined(orderBy[0])) { const firstOrderBy = orderBy?.[0]; const key = Object.keys(firstOrderBy)[0]; filteredData.sort((itemA, itemB) => { const itemAValue = itemA[key as unknown as keyof typeof itemA]; const itemBValue = itemB[key as unknown as keyof typeof itemB]; if (!itemAValue || !itemBValue) { return 0; } const sortDirection = firstOrderBy[key as unknown as keyof typeof firstOrderBy]; if (isString(itemAValue) && isString(itemBValue)) { return sortDirection === 'desc' ? itemBValue.localeCompare(itemAValue) : -itemBValue.localeCompare(itemAValue); } return 0; }); } if (isNumber(limit) && limit > 0) { filteredData = filteredData.slice(0, limit); } return filteredData; }; export const fetchOneFromData = ( data: Array, id: string, ): DataT | undefined => { if (!isDefined(id)) { throw new Error( `id is not defined in updateOneFromData, check that you provided where.id if needed.`, ); } return data.filter((item) => item.id === id)[0]; }; export const updateOneFromData = ( data: Array, id: string | undefined, payload: GraphQLVariables, ): DataT | undefined => { if (!isDefined(id)) { throw new Error( `id is not defined in updateOneFromData, check that you provided where.id if needed.`, ); } const object = data.filter((item) => item.id === id)[0]; const newObject = Object.assign(object, payload); return newObject; };