import { equals, identity } from 'remeda' import { z } from 'zod' import { isEqualByD, isEqualDC } from './lodash' import { Mapper } from './Mapper' import { todo } from './todo' export type Filter = (value: Val) => boolean export type FilterP = (value: Val) => Promise export type FilterOptional = (value: Val) => boolean | undefined export type FilterOptionalP = (value: Val) => Promise export const AlwaysTrue = (value: Val) => true export const AlwaysTrueP = async (value: Val) => true export const TodoFilter = (value: Val): boolean => { return todo() } export const TodoFilterP = async (value: Val): Promise => { return todo() } export const getStaticFilterP = (value: Val) => async ($value: Val) => equals(value, $value) export const getStaticFilterByP = (value: Val, mapper: Mapper) => async ($value: Val) => isEqualByD(value, $value, mapper) export const getStaticMultiFilter = (values: Val[]) => async ($value: Val) => values.find(isEqualDC($value)) !== undefined export const toFilter = (getter: (input: In) => Out) => (input: In) => Boolean(getter(input)) export const toFilterP = (getter: (input: In) => Promise) => async (input: In) => Boolean(await getter(input)) export const not = (filter: Filter): Filter => (value: Val) => !filter(value) export const notP = (filter: FilterP): FilterP => async (value: Val) => !(await filter(value)) export const and = (filters: Filter[]): Filter => (value: Val) => filters.every(filter => filter(value)) export const andP = (filters: FilterP[]) => async (value: Val) => (await Promise.all(filters.map(filter => filter(value)))).every(identity) export const or = (filters: Filter[]): Filter => (value: Val) => filters.some(filter => filter(value)) export const without = (objects: T[], filters: Filter[]) => objects.every(a => !filters.some(f => f(a))) export const only = (objects: T[], filters: Filter[]) => objects.every(a => filters.some(f => f(a))) export function getFilterStubP(name: string) { // const obj = { [name]: UnimplementedFilter } // return obj[name] return TodoFilterP } export function getFilterStubsP(names: string[]) { return names.map(getFilterStubP) } export type FilterTwo = (a: A, b: B) => boolean export type FilterTwoP = (a: A, b: B) => Promise export const BooleanFilterSchema = z.function().args(z.boolean()).returns(z.boolean()) export type BooleanFilter = z.infer