-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
filters.ts
107 lines (98 loc) · 3.61 KB
/
filters.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import type { MappedFieldNames } from './functions.js';
import type { FieldOutputMap } from './output.js';
import type { RelationalFields } from './schema.js';
import type { IfNever, IsDateTime, IsNumber, IsString, MergeOptional, UnpackList } from './utils.js';
/**
* Filters
*/
export type QueryFilter<Schema extends object, Item> = WrapLogicalFilters<NestedQueryFilter<Schema, Item>>;
/**
* Query filters without logical filters
*/
export type NestedQueryFilter<Schema extends object, Item> = UnpackList<Item> extends infer FlatItem
? MergeOptional<
{
[Field in keyof FlatItem]?: NestedRelationalFilter<Schema, FlatItem, Field>;
},
MappedFieldNames<Schema, Item> extends infer Funcs
? {
[Func in keyof Funcs]?: Funcs[Func] extends infer Field
? Field extends keyof FlatItem
? NestedRelationalFilter<Schema, FlatItem, Field>
: never
: never;
}
: never
>
: never;
/**
* Allow for relational filters
*/
export type NestedRelationalFilter<Schema extends object, Item, Field extends keyof Item> =
| (Field extends RelationalFields<Schema, Item>
? WrapRelationalFilters<NestedQueryFilter<Schema, Item[Field]>>
: never)
| FilterOperators<Item[Field]>;
/**
* All regular filter operators
*
* TODO would love to filter this based on field type but thats not accurate enough in the schema atm
*/
export type FilterOperators<
FieldType,
T = FieldType extends keyof FieldOutputMap ? FieldOutputMap[FieldType] : FieldType,
> = MapFilterOperators<{
_eq: T;
_neq: T;
_gt: IsDateTime<FieldType, string, IsNumber<T, number, never>>;
_gte: IsDateTime<FieldType, string, IsNumber<T, number, never>>;
_lt: IsDateTime<FieldType, string, IsNumber<T, number, never>>;
_lte: IsDateTime<FieldType, string, IsNumber<T, number, never>>;
_in: T[];
_nin: T[];
_between: IsDateTime<FieldType, [T, T], IsNumber<T, [T, T], never>>;
_nbetween: IsDateTime<FieldType, [T, T], IsNumber<T, [T, T], never>>;
_contains: IsDateTime<FieldType, never, IsString<T, string, never>>;
_ncontains: IsDateTime<FieldType, never, IsString<T, string, never>>;
_starts_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_istarts_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_nstarts_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_nistarts_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_ends_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_iends_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_nends_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_niends_with: IsDateTime<FieldType, never, IsString<T, string, never>>;
_empty: boolean;
_nempty: boolean;
_nnull: boolean;
_null: boolean;
_intersects: T;
_nintersects: T;
_intersects_bbox: T;
_nintersects_bbox: T;
// regex is not available over the API https://docs.directus.io/reference/filter-rules.html#filter-operators
// _regex: IsDateTime<FieldType, never, IsString<T, string, never>>;
}>;
// filter not applicable filters based on "never" types
type MapFilterOperators<Filters extends object> = {
[Key in keyof Filters as IfNever<Filters[Key], never, Key>]?: Filters[Key];
};
/**
* Relational filter operators
*/
export type RelationalFilterOperators = '_some' | '_none';
export type WrapRelationalFilters<Filters> =
| {
[Operator in RelationalFilterOperators]?: Filters;
}
| Filters;
/**
* Logical filter operations
*/
export type LogicalFilterOperators = '_or' | '_and';
export type WrapLogicalFilters<Filters extends object> = MergeOptional<
{
[Operator in LogicalFilterOperators]?: WrapLogicalFilters<Filters>[];
},
Filters
>;