@@ -132,21 +132,100 @@ export async function runFirebasePlugin(
132132
133133 if ( actionName === "FS.QueryFireStore" ) {
134134 const data = await withFirestoreCollection ( async ( ref ) => {
135+ const structuredQuery = actionData . query ;
136+ if ( ! structuredQuery ) {
137+ throw badRequest ( "Missing structuredQuery in action data" ) ;
138+ }
139+
135140 let query : FirebaseFirestore . Query < FirebaseFirestore . DocumentData > = ref ;
141+
142+ // Apply `where` filters
143+ if ( structuredQuery . where && structuredQuery . where . fieldFilter ) {
144+ const fieldFilter = structuredQuery . where . fieldFilter ;
145+ const fieldPath = fieldFilter . field ?. fieldPath ;
146+ const operator = fieldFilter . op ;
147+ const value = fieldFilter . value ;
148+
149+ if ( ! fieldPath || ! operator || value === undefined ) {
150+ throw badRequest ( "Invalid fieldFilter in where clause" ) ;
151+ }
152+
153+ let firestoreOp : FirebaseFirestore . WhereFilterOp ;
154+ switch ( operator ) {
155+ case "EQUAL" :
156+ firestoreOp = "==" ;
157+ break ;
158+ case "GREATER_THAN" :
159+ firestoreOp = ">" ;
160+ break ;
161+ case "LESS_THAN" :
162+ firestoreOp = "<" ;
163+ break ;
164+ case "GREATER_THAN_OR_EQUAL" :
165+ firestoreOp = ">=" ;
166+ break ;
167+ case "LESS_THAN_OR_EQUAL" :
168+ firestoreOp = "<=" ;
169+ break ;
170+ case "ARRAY_CONTAINS" :
171+ firestoreOp = "array-contains" ;
172+ break ;
173+ default :
174+ throw badRequest ( `Unsupported operator: ${ operator } ` ) ;
175+ }
176+
177+ const actualValue = value . integerValue ?? value . stringValue ?? value . booleanValue ?? value . doubleValue ;
178+ if ( actualValue === undefined ) {
179+ throw badRequest ( "Unsupported value type in structuredQuery" ) ;
180+ }
136181
137- // Parse Query JSON from actionData.query
138- if ( actionData . query ) {
139- for ( const condition of actionData . query ) {
140- const { field, op, value } = condition ;
141- if ( ! field || ! op || value === undefined ) {
142- throw badRequest ( "Invalid query condition: " + JSON . stringify ( condition ) ) ;
182+ query = query . where ( fieldPath , firestoreOp , actualValue ) ;
183+ }
184+
185+ // Apply `orderBy`
186+ if ( structuredQuery . orderBy && Array . isArray ( structuredQuery . orderBy ) ) {
187+ for ( const order of structuredQuery . orderBy ) {
188+ if ( order . field && order . field . fieldPath ) {
189+ query = query . orderBy (
190+ order . field . fieldPath ,
191+ ( order . direction || "asc" ) as FirebaseFirestore . OrderByDirection
192+ ) ;
143193 }
144- query = query . where ( field , op as WhereFilterOp , value ) ;
145194 }
146195 }
147-
148- // Execute the query and retrieve results
196+
197+ // Apply `limit`
198+ if ( structuredQuery . limit ) {
199+ query = query . limit ( structuredQuery . limit ) ;
200+ }
201+
202+ // Apply `offset` (Firestore SDK doesn't support offset directly; simulate it with startAfter)
203+ if ( structuredQuery . offset ) {
204+ const offsetSnapshot = await query . limit ( structuredQuery . offset ) . get ( ) ;
205+ const lastVisible = offsetSnapshot . docs [ offsetSnapshot . docs . length - 1 ] ;
206+ if ( lastVisible ) {
207+ query = query . startAfter ( lastVisible ) ;
208+ }
209+ }
210+
211+ // Apply `startAt` and `endAt` cursors, checking for undefined values
212+ if ( structuredQuery . startAt && structuredQuery . startAt . values ) {
213+ const startAtValues = structuredQuery . startAt . values . map ( ( v : { integerValue : any ; stringValue : any ; booleanValue : any ; doubleValue : any ; } ) => v . integerValue ?? v . stringValue ?? v . booleanValue ?? v . doubleValue ) . filter ( ( value : any ) => value !== undefined ) ;
214+ if ( startAtValues . length > 0 ) {
215+ query = query . startAt ( ...startAtValues ) ;
216+ }
217+ }
218+
219+ if ( structuredQuery . endAt && structuredQuery . endAt . values ) {
220+ const endAtValues = structuredQuery . endAt . values . map ( ( v : { integerValue : any ; stringValue : any ; booleanValue : any ; doubleValue : any ; } ) => v . integerValue ?? v . stringValue ?? v . booleanValue ?? v . doubleValue ) . filter ( ( value : any ) => value !== undefined ) ;
221+ if ( endAtValues . length > 0 ) {
222+ query = query . endAt ( ...endAtValues ) ;
223+ }
224+ }
225+
226+ // Execute the query
149227 const snapshot = await query . get ( ) ;
228+
150229 if ( snapshot . empty ) {
151230 return [ ] ;
152231 }
0 commit comments