@@ -27,37 +27,97 @@ class MockDriver implements Driver {
2727 async find ( objectName : string , query : any ) {
2828 let items = this . data [ objectName ] || [ ] ;
2929
30- // Apply filters if provided
30+ // Apply filters if provided (supports FilterNode array format)
3131 if ( query && query . filters ) {
32- const filters = query . filters ;
33- if ( typeof filters === 'object' ) {
34- const filterKeys = Object . keys ( filters ) ;
35- if ( filterKeys . length > 0 ) {
36- items = items . filter ( item => {
37- for ( const [ key , value ] of Object . entries ( filters ) ) {
38- if ( item [ key ] !== value ) {
39- return false ;
40- }
41- }
42- return true ;
43- } ) ;
44- }
45- }
32+ items = items . filter ( item => this . matchesFilter ( item , query . filters ) ) ;
4633 }
4734
48- // Apply skip and limit if provided
35+ // Apply skip and top/ limit if provided (QueryAST uses 'top' for limit)
4936 if ( query ) {
5037 if ( query . skip ) {
5138 items = items . slice ( query . skip ) ;
5239 }
53- if ( query . limit ) {
54- items = items . slice ( 0 , query . limit ) ;
40+ if ( query . top || query . limit ) {
41+ items = items . slice ( 0 , query . top || query . limit ) ;
5542 }
5643 }
5744
5845 return items ;
5946 }
60-
47+
48+ /**
49+ * Matches an item against a filter condition
50+ * @param item - The data item to test
51+ * @param filter - The filter in FilterNode array format or simple object format
52+ * FilterNode format: [field, op, value] for single condition
53+ * Complex filters: [[field, op, value], 'and', [field2, op2, value2]]
54+ * Simple format: { field: value }
55+ * @returns true if item matches the filter
56+ */
57+ private matchesFilter ( item : any , filter : any ) : boolean {
58+ if ( ! filter ) return true ;
59+
60+ // Handle FilterNode array format: [[field, op, value]] or [[field, op, value], 'and', [field2, op2, value2]]
61+ if ( Array . isArray ( filter ) ) {
62+ // Single condition: [field, op, value]
63+ if ( filter . length === 3 && typeof filter [ 0 ] === 'string' ) {
64+ const [ field , op , value ] = filter ;
65+ return this . evaluateCondition ( item , field , op , value ) ;
66+ }
67+
68+ // Multiple conditions with logical operators
69+ let result = true ;
70+ let currentOp = 'and' ;
71+ for ( let i = 0 ; i < filter . length ; i ++ ) {
72+ const element = filter [ i ] ;
73+ if ( typeof element === 'string' ) {
74+ currentOp = element ; // 'and' or 'or'
75+ } else if ( Array . isArray ( element ) ) {
76+ const conditionResult = this . matchesFilter ( item , element ) ;
77+ if ( currentOp === 'and' ) {
78+ result = result && conditionResult ;
79+ } else if ( currentOp === 'or' ) {
80+ result = result || conditionResult ;
81+ }
82+ }
83+ }
84+ return result ;
85+ }
86+
87+ // Handle simple object format: { field: value }
88+ if ( typeof filter === 'object' ) {
89+ for ( const [ key , value ] of Object . entries ( filter ) ) {
90+ if ( item [ key ] !== value ) {
91+ return false ;
92+ }
93+ }
94+ return true ;
95+ }
96+
97+ return true ;
98+ }
99+
100+ /**
101+ * Evaluates a single filter condition
102+ * @param item - The data item to test
103+ * @param field - The field name
104+ * @param op - The operator: '=', '!=', '>', '>=', '<', '<=', 'in'
105+ * @param value - The value to compare against
106+ * @returns true if the condition is satisfied
107+ */
108+ private evaluateCondition ( item : any , field : string , op : string , value : any ) : boolean {
109+ const fieldValue = item [ field ] ;
110+ switch ( op ) {
111+ case '=' : return fieldValue === value ;
112+ case '!=' : return fieldValue !== value ;
113+ case '>' : return fieldValue > value ;
114+ case '>=' : return fieldValue >= value ;
115+ case '<' : return fieldValue < value ;
116+ case '<=' : return fieldValue <= value ;
117+ case 'in' : return Array . isArray ( value ) ? value . includes ( fieldValue ) : false ;
118+ default : return true ;
119+ }
120+ }
61121 async findOne ( objectName : string , id : string | number , query ?: any , options ?: any ) {
62122 const items = this . data [ objectName ] || [ ] ;
63123 if ( id !== undefined && id !== null ) {
@@ -97,7 +157,13 @@ class MockDriver implements Driver {
97157 }
98158
99159 async count ( objectName : string , query : any ) {
100- return ( this . data [ objectName ] || [ ] ) . length ;
160+ // Count should apply filters but not skip/limit
161+ const countQuery = { ...query } ;
162+ delete countQuery . skip ;
163+ delete countQuery . top ;
164+ delete countQuery . limit ;
165+ const items = await this . find ( objectName , countQuery ) ;
166+ return items . length ;
101167 }
102168
103169 async createMany ( objectName : string , data : any [ ] ) {
0 commit comments