@gblikas/querykit 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Type definitions for Virtual Fields support
3
+ */
4
+
5
+ import {
6
+ QueryExpression,
7
+ IComparisonExpression,
8
+ ComparisonOperator
9
+ } from '../parser/types';
10
+
11
+ /**
12
+ * Base interface for query context.
13
+ * Users can extend this interface with their own context properties.
14
+ */
15
+ export interface IQueryContext {
16
+ [key: string]: unknown;
17
+ }
18
+
19
+ /**
20
+ * Input provided to a virtual field resolver.
21
+ * Contains the parsed field, operator, and value from the query.
22
+ */
23
+ export interface IVirtualFieldInput {
24
+ /**
25
+ * The virtual field name (e.g., "my")
26
+ */
27
+ field: string;
28
+
29
+ /**
30
+ * The comparison operator used (e.g., ":", ">", "<", etc.)
31
+ * Maps to ComparisonOperator type
32
+ */
33
+ operator: string;
34
+
35
+ /**
36
+ * The value provided in the query
37
+ */
38
+ value: string;
39
+ }
40
+
41
+ /**
42
+ * Helper type to filter out index signatures from a type
43
+ */
44
+ type KnownKeys<T> = {
45
+ [K in keyof T]: string extends K ? never : number extends K ? never : K;
46
+ } extends { [_ in keyof T]: infer U }
47
+ ? U
48
+ : never;
49
+
50
+ /**
51
+ * Utility type to extract all field names from a schema.
52
+ * Recursively extracts field names from nested tables, excluding index signatures.
53
+ */
54
+ export type AllSchemaFields<TSchema extends Record<string, object>> = {
55
+ [K in KnownKeys<TSchema>]: TSchema[K] extends { [key: string]: unknown }
56
+ ? keyof TSchema[K] & string
57
+ : never;
58
+ }[KnownKeys<TSchema>];
59
+
60
+ /**
61
+ * Type-safe mapping from allowed values to schema fields.
62
+ * Ensures all keys in TKeys map to valid fields in the schema.
63
+ */
64
+ export type SchemaFieldMap<
65
+ TKeys extends string,
66
+ TSchema extends Record<string, object>
67
+ > = Record<TKeys, AllSchemaFields<TSchema>>;
68
+
69
+ /**
70
+ * Helper functions provided to virtual field resolvers.
71
+ *
72
+ * Note: The fields() method is generic at the method level, not the interface level.
73
+ * This allows TypeScript to infer TValues from the mapping object passed at call-time,
74
+ * eliminating the need for type assertions while maintaining full type safety.
75
+ */
76
+ export interface IResolverHelpers<TSchema extends Record<string, object>> {
77
+ /**
78
+ * Type-safe field mapping helper.
79
+ * Ensures all allowedValues are mapped to valid schema fields.
80
+ *
81
+ * The generic TValues parameter is inferred from the keys in the mapping object,
82
+ * providing full type safety without requiring explicit type annotations.
83
+ *
84
+ * @example
85
+ * const fieldMap = fields({
86
+ * assigned: 'assignee_id',
87
+ * created: 'creator_id'
88
+ * });
89
+ * // TypeScript infers TValues as 'assigned' | 'created'
90
+ */
91
+ fields: <TValues extends string>(
92
+ mapping: SchemaFieldMap<TValues, TSchema>
93
+ ) => SchemaFieldMap<TValues, TSchema>;
94
+ }
95
+
96
+ /**
97
+ * Schema-constrained comparison expression.
98
+ * Ensures field names are valid schema fields.
99
+ */
100
+ export interface ITypedComparisonExpression<
101
+ TFields extends string = string
102
+ > extends Omit<IComparisonExpression, 'field'> {
103
+ type: 'comparison';
104
+ field: TFields;
105
+ operator: ComparisonOperator;
106
+ value:
107
+ | string
108
+ | number
109
+ | boolean
110
+ | null
111
+ | Array<string | number | boolean | null>;
112
+ }
113
+
114
+ /**
115
+ * Schema-constrained query expression.
116
+ * Can be a comparison or logical expression with typed fields.
117
+ */
118
+ export type ITypedQueryExpression<TFields extends string = string> =
119
+ | ITypedComparisonExpression<TFields>
120
+ | QueryExpression;
121
+
122
+ /**
123
+ * Definition for a virtual field.
124
+ * Configures how a virtual field should be resolved at query execution time.
125
+ */
126
+ export interface IVirtualFieldDefinition<
127
+ TSchema extends Record<string, object>,
128
+ TContext extends IQueryContext = IQueryContext,
129
+ TValues extends string = string
130
+ > {
131
+ /**
132
+ * Allowed values for this virtual field.
133
+ * Use `as const` for type inference.
134
+ *
135
+ * @example
136
+ * allowedValues: ['assigned', 'created', 'watching'] as const
137
+ */
138
+ allowedValues: readonly TValues[];
139
+
140
+ /**
141
+ * Whether to allow comparison operators beyond `:` (equality).
142
+ * If false, only `:` is allowed. If true, `:>`, `:<`, etc. are permitted.
143
+ *
144
+ * @default false
145
+ */
146
+ allowOperators?: boolean;
147
+
148
+ /**
149
+ * Resolve the virtual field to a real query expression.
150
+ * The `fields` helper ensures type-safe field references.
151
+ *
152
+ * @param input - The parsed virtual field input (field, operator, value)
153
+ * @param context - Runtime context provided by createContext()
154
+ * @param helpers - Helper functions including type-safe fields() helper
155
+ * @returns A query expression that replaces the virtual field
156
+ *
157
+ * @example
158
+ * resolve: (input, ctx, { fields }) => {
159
+ * const fieldMap = fields({
160
+ * assigned: 'assignee_id',
161
+ * created: 'creator_id'
162
+ * });
163
+ * return {
164
+ * type: 'comparison',
165
+ * field: fieldMap[input.value],
166
+ * operator: '==',
167
+ * value: ctx.currentUserId
168
+ * };
169
+ * }
170
+ */
171
+ resolve: (
172
+ input: IVirtualFieldInput & { value: TValues },
173
+ context: TContext,
174
+ helpers: IResolverHelpers<TSchema>
175
+ ) => ITypedQueryExpression<AllSchemaFields<TSchema>>;
176
+
177
+ /**
178
+ * Human-readable description (for autocomplete UI).
179
+ * Optional metadata for documentation and tooling.
180
+ */
181
+ description?: string;
182
+
183
+ /**
184
+ * Descriptions for each allowed value (for autocomplete UI).
185
+ * Optional metadata for documentation and tooling.
186
+ */
187
+ valueDescriptions?: Partial<Record<TValues, string>>;
188
+ }
189
+
190
+ /**
191
+ * Configuration for all virtual fields in a QueryKit instance.
192
+ *
193
+ * Note: Uses a flexible type for the values to allow each virtual field definition
194
+ * to have its own specific TValues type (e.g., 'assigned' | 'created' for one field,
195
+ * 'high' | 'low' for another). The IResolverHelpers.fields() method infers these
196
+ * types at call-time, maintaining type safety without needing explicit annotations.
197
+ */
198
+ export type VirtualFieldsConfig<
199
+ TSchema extends Record<string, object> = Record<string, object>,
200
+ TContext extends IQueryContext = IQueryContext
201
+ > = {
202
+ [fieldName: string]: IVirtualFieldDefinition<TSchema, TContext, string>;
203
+ };