import type { Where } from "../services/Store.js" import type { FieldValues } from "./filter/types/fields.js" import type { FieldPath, FieldPathValue } from "./filter/types/path/eager.js" /** * the function defaults to "eq", but has additional properties for notEq, in and notIn */ export interface WhereFilter extends ReturnType> {} export function makeWhereFilter() { const f = makeWhereFilter_() return f as WhereFilter } function makeHelpers() { const helpers = makeHelpers_() return helpers as WhereHelpers } export interface WhereHelpers extends ReturnType> {} function makeHelpers_() { type Paths = FieldPath type Value = FieldPathValue return { in>( this: void, path: TFieldName, value: readonly V[] ) { return { key: path, value, t: "in" as const } }, notIn>( this: void, path: TFieldName, value: readonly V[] ) { return { key: path, value, t: "not-in" as const } }, eq>( this: void, path: TFieldName, value: V ) { return { key: path, value, t: "eq" as const } }, notEq>( this: void, path: TFieldName, value: V ) { return { key: path, value, t: "not-eq" as const } } } satisfies Record Where> } function makeWhereFilter_() { const helpers = makeHelpers() const f = Object.assign(helpers.eq, helpers) return f } export type WhereValue< T extends "eq" | "not-eq" | "starts-with" | "ends-with" | "includes" | "contains" | "not-contains", A, // extends SupportedValues, V extends A = A > = { t: T; v: V } type SupportedValues = string | boolean | number | null export type WhereIn = { t: T v: Values } /** * @tsplus fluent Iterable $contains */ export function $contains( _: readonly A[], v: V ): WhereValue<"contains", A, V> { return $$contains(v) } /** * @tsplus fluent Iterable $notContains */ export function $notContains( _: readonly A[], v: V ): WhereValue<"not-contains", A, V> { return $$notContains(v) } /** * @tsplus fluent string $in * @tsplus fluent boolean $in * @tsplus fluent number $in */ export function $in( _: A, ...v: Values ): WhereIn<"in", A, Values> { return $$in(v) } /** * @tsplus fluent string $notIn * @tsplus fluent boolean $notIn * @tsplus fluent number $notIn */ export function $notIn( _: A, ...v: Values ): WhereIn<"not-in", A, Values> { return $$notIn(v) } /** * @tsplus fluent string $is * @tsplus fluent boolean $is * @tsplus fluent number $is * @tsplus fluent Object $is */ export function $is(_: A, v: V): WhereValue<"eq", A, V> { return $$is(v) } /** * @tsplus fluent string $isnt * @tsplus fluent boolean $isnt * @tsplus fluent number $isnt * @tsplus fluent Object $isnt */ export function $isnt(_: A, v: V): WhereValue<"not-eq", A, V> { return $$isnt(v) } function $is__(v: V) { return (_: A) => $is(_, v) } function $isnt__(v: V) { return (_: A) => $isnt(_, v) } function $in__( ...v: Values ) { return (_: A) => $in(_, ...v) } function $notIn__( ...v: Values ) { return (_: A) => $notIn(_, ...v) } // function $contains__( // v: V // ) { // return (_: readonly A[]) => $contains(_, v) // } // function $notContains__( // v: V // ) { // return (_: readonly A[]) => $notContains(_, v) // } export const Filters = { $is: $is__, $isnt: $isnt__, $in: $in__, $notIn: $notIn__, // $contains: $contains__, // $notContains: $notContains__, } /** * @tsplus fluent string $startsWith */ export function $startsWith(_: A, v: V): WhereValue<"starts-with", A, V> { return $$startsWith(v) } /** * @tsplus fluent string $endsWith */ export function $endsWith(_: A, v: V): WhereValue<"ends-with", A, V> { return $$endsWith(v) } /** * @tsplus fluent string $includes */ export function $includes(_: A, v: V): WhereValue<"includes", A, V> { return $$includes(v) } function $$in(v: L) { return { t: "in" as const, v } } function $$notIn(v: L) { return { t: "not-in" as const, v } } function $$is(v: A) { return { t: "eq" as const, v } } function $$isnt(v: A) { return { t: "not-eq" as const, v } } // containsAny, containsAll? function $$contains(v: A) { return { t: "contains" as const, v } } function $$notContains(v: A) { return { t: "not-contains" as const, v } } function $$includes(v: A) { return { t: "includes" as const, v } } function $$startsWith(v: A) { return { t: "starts-with" as const, v } } function $$endsWith(v: A) { return { t: "ends-with" as const, v } } type ValueType = { t: "in" | "not-in" v: readonly V[] } | { t: "eq" | "not-eq"; v: V } type TType = T extends ValueType ? T["t"] : never type VType = T extends ValueType ? T["v"] : never function f(p: string, b: any) { if (typeof b === "function") b = b(undefined) const obj = typeof b === "object" && b !== null return makeFilter(p, obj ? b.v : b, obj ? b.t ?? "eq" : "eq"); } function makeFilter(path: string, value: any, t: T) { return { key: path, t, value } } type FIL = { key: K t: T value: V readonly S: S } export function makeFilters() { type Paths = FieldPath type Value = FieldPathValue function test< TFieldName extends Paths, A extends Value, Val >( path: TFieldName, value: (v: A) => Val ): FIL, VType> function test< TFieldName extends Paths, A extends Value >( path: TFieldName, value: A ): FIL function test(p: string, v: any) { return f(p, v) as any } return test } // export function makeFilter() { // const f = makeFilter_() // return f as WhereFilterHelper // } // export interface WhereFilterHelper extends ReturnType> {} // function makeFilter_() { // function eq, V extends FieldPathValue>( // path: TFieldName, // value: V // ) { // return { key: path, value, t: "eq" as const } // } // const f = Object.assign(eq satisfies (...args: any[]) => Where, { // in, V extends FieldPathValue>( // path: TFieldName, // value: readonly V[] // ) { // return { key: path, value, t: "in" as const } // }, // notIn, V extends FieldPathValue>( // path: TFieldName, // value: readonly V[] // ) { // return { key: path, value, t: "not-in" as const } // }, // eq, // notEq, V extends FieldPathValue>( // path: TFieldName, // value: V // ) { // return { key: path, value, t: "not-eq" as const } // } // } satisfies Record Where>) // return f // }