import type { ColumnFiltersState, PaginationState, SortingState } from '@tanstack/react-table'; import type { FilterOption, Options, SortOption } from '@warkypublic/resolvespec-js'; const OPERATOR_MAP: Record = { between: 'between', contains: 'ilike', endsWith: 'endswith', equals: 'eq', excludes: 'in', greaterThan: 'gt', greaterThanOrEqual: 'gte', includes: 'in', is: 'eq', isAfter: 'gt', isBefore: 'lt', isBetween: 'between_inclusive', isEmpty: 'is_null', isFalse: 'eq', isNotEmpty: 'is_not_null', isTrue: 'eq', lessThan: 'lt', lessThanOrEqual: 'lte', notContains: 'ilike', notEquals: 'neq', startsWith: 'startswith', }; export function applyCursor(opts: Options, cursor: null | string, limit: number): Options { const result = { ...opts, limit }; if (cursor) { result.cursor_forward = cursor; } return result; } export function buildOptions( sorting: SortingState, filters: ColumnFiltersState, pagination: PaginationState | undefined, columnMap?: Record, defaultOptions?: Partial ): Options { const opts: Options = { ...defaultOptions }; if (sorting.length > 0) { opts.sort = mapSorting(sorting, columnMap); } if (filters.length > 0) { opts.filters = mapFilters(filters, columnMap); } if (pagination) { const { limit, offset } = mapPagination(pagination); opts.limit = limit; opts.offset = offset; } return opts; } export function mapFilters( filters: ColumnFiltersState, columnMap?: Record ): FilterOption[] { return filters.flatMap((filter) => { const filterValue = filter.value as any; // Enum filter with values array if (filterValue?.values && Array.isArray(filterValue.values)) { return [ { column: resolveColumn(filter.id, columnMap), operator: 'in', value: filterValue.values, }, ]; } const operator = filterValue?.operator ?? 'eq'; const value = filterValue?.value ?? filterValue; return [ { column: resolveColumn(filter.id, columnMap), operator: resolveOperator(operator), value: resolveFilterValue(operator, value), }, ]; }); } export function mapPagination(pagination: PaginationState): { limit: number; offset: number } { return { limit: pagination.pageSize, offset: pagination.pageIndex * pagination.pageSize, }; } export function mapSorting( sorting: SortingState, columnMap?: Record ): SortOption[] { return sorting.map(({ desc, id }) => ({ column: resolveColumn(id, columnMap), direction: desc ? ('desc' as const) : ('asc' as const), })); } function resolveColumn(id: string, columnMap?: Record): string { return columnMap?.[id] ?? id; } function resolveFilterValue(operator: string, value: any): any { if (operator === 'isTrue') return true; if (operator === 'isFalse') return false; if (operator === 'contains') return `%${value}%`; if (operator === 'startsWith') return `${value}%`; if (operator === 'endsWith') return `%${value}`; if (operator === 'notContains') return `%${value}%`; return value; } function resolveOperator(op: string): string { return OPERATOR_MAP[op] ?? op; }