@@ -22,6 +22,21 @@ import { z } from 'zod';
2222 * 4. Convention over Configuration: Implicit syntax for common queries
2323 */
2424
25+ /**
26+ * Field Reference
27+ * Represents a reference to another field/column instead of a literal value.
28+ * Used for joins (ON clause) and cross-field comparisons.
29+ *
30+ * @example
31+ * // user.id = order.owner_id
32+ * { "$eq": { "$field": "order.owner_id" } }
33+ */
34+ export const FieldReferenceSchema = z . object ( {
35+ $field : z . string ( ) . describe ( 'Field Reference/Column Name' )
36+ } ) ;
37+
38+ export type FieldReference = z . infer < typeof FieldReferenceSchema > ;
39+
2540// ============================================================================
2641// 3.1 Comparison Operators
2742// ============================================================================
@@ -44,16 +59,16 @@ export const EqualityOperatorSchema = z.object({
4459 */
4560export const ComparisonOperatorSchema = z . object ( {
4661 /** Greater than - SQL: > | MongoDB: $gt */
47- $gt : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
62+ $gt : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
4863
4964 /** Greater than or equal to - SQL: >= | MongoDB: $gte */
50- $gte : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
65+ $gte : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
5166
5267 /** Less than - SQL: < | MongoDB: $lt */
53- $lt : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
68+ $lt : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
5469
5570 /** Less than or equal to - SQL: <= | MongoDB: $lte */
56- $lte : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
71+ $lte : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
5772} ) ;
5873
5974// ============================================================================
@@ -78,8 +93,8 @@ export const SetOperatorSchema = z.object({
7893export const RangeOperatorSchema = z . object ( {
7994 /** Between (inclusive) - takes [min, max] array */
8095 $between : z . tuple ( [
81- z . union ( [ z . number ( ) , z . date ( ) ] ) ,
82- z . union ( [ z . number ( ) , z . date ( ) ] )
96+ z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) ,
97+ z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] )
8398 ] ) . optional ( ) ,
8499} ) ;
85100
@@ -131,17 +146,17 @@ export const FieldOperatorsSchema = z.object({
131146 $ne : z . any ( ) . optional ( ) ,
132147
133148 // Comparison (numeric/date)
134- $gt : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
135- $gte : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
136- $lt : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
137- $lte : z . union ( [ z . number ( ) , z . date ( ) ] ) . optional ( ) ,
149+ $gt : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
150+ $gte : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
151+ $lt : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
152+ $lte : z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) . optional ( ) ,
138153
139154 // Set & Range
140155 $in : z . array ( z . any ( ) ) . optional ( ) ,
141156 $nin : z . array ( z . any ( ) ) . optional ( ) ,
142157 $between : z . tuple ( [
143- z . union ( [ z . number ( ) , z . date ( ) ] ) ,
144- z . union ( [ z . number ( ) , z . date ( ) ] )
158+ z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] ) ,
159+ z . union ( [ z . number ( ) , z . date ( ) , FieldReferenceSchema ] )
145160 ] ) . optional ( ) ,
146161
147162 // String-specific
0 commit comments