|  | 
| 5 | 5 |   CollectionReference, | 
| 6 | 6 |   DocumentReference, | 
| 7 | 7 |   getFirestore, | 
|  | 8 | +  WhereFilterOp, | 
| 8 | 9 |   OrderByDirection, | 
| 9 | 10 | } from "firebase-admin/firestore"; | 
| 10 | 11 | import { DataSourceDataType } from "./dataSourceConfig"; | 
| @@ -83,37 +84,77 @@ export async function runFirebasePlugin( | 
| 83 | 84 |       return collections.map((i) => i.id); | 
| 84 | 85 |     } | 
| 85 | 86 | 
 | 
| 86 |  | -    if (actionName === "FS.QueryFireStore") { | 
|  | 87 | +    if (actionName === "FS.ListFireStore") { | 
| 87 | 88 |       const data = await withFirestoreCollection(async (ref) => { | 
| 88 |  | -        let query; | 
|  | 89 | +     | 
|  | 90 | +        // Initialize query as a Query type, not CollectionReference | 
|  | 91 | +        let query: FirebaseFirestore.Query<FirebaseFirestore.DocumentData> = ref; | 
|  | 92 | +     | 
|  | 93 | +        // Sorting | 
| 89 | 94 |         if (actionData.orderBy) { | 
| 90 |  | -          console.log("orderBy", actionData.orderBy); | 
| 91 |  | -          query = ref.orderBy( | 
|  | 95 | +          query = query.orderBy( | 
| 92 | 96 |             actionData.orderBy, | 
| 93 | 97 |             (actionData.orderDirection || "asc") as OrderByDirection | 
| 94 | 98 |           ); | 
| 95 | 99 |         } | 
| 96 |  | -        // Apply startAt if specified (for pagination) | 
| 97 |  | -        if (actionData.startAt) { | 
| 98 |  | -          if (Array.isArray(actionData.startAt)) { | 
| 99 |  | -              // If startAt is an array, pass it as is | 
| 100 |  | -              query = (query || ref).startAt(...actionData.startAt); | 
| 101 |  | -          } else { | 
| 102 |  | -              // If startAt is a single value, use it directly | 
| 103 |  | -              query = (query || ref).startAt(actionData.startAt); | 
|  | 100 | +     | 
|  | 101 | +        // Get the total count using aggregate query | 
|  | 102 | +        const totalCount = await query.count().get().then((snapshot) => snapshot.data().count); | 
|  | 103 | +     | 
|  | 104 | +        // Pagination | 
|  | 105 | +        const pageSize = actionData.pageSize || 10; | 
|  | 106 | +        const pageNumber = actionData.pageNumber || 1; | 
|  | 107 | +        const offset = (pageNumber - 1) * pageSize; | 
|  | 108 | +     | 
|  | 109 | +        // Move to the starting point based on offset | 
|  | 110 | +        if (offset > 0) { | 
|  | 111 | +          const offsetSnapshot = await query.limit(offset).get(); | 
|  | 112 | +          const lastVisible = offsetSnapshot.docs[offsetSnapshot.docs.length - 1]; | 
|  | 113 | +     | 
|  | 114 | +          // If we have a valid last document, use it to start the next page | 
|  | 115 | +          if (lastVisible) { | 
|  | 116 | +            query = query.startAfter(lastVisible); | 
| 104 | 117 |           } | 
| 105 | 118 |         } | 
| 106 |  | -        if (actionData.limit > 0) { | 
| 107 |  | -          query = (query || ref).limit(actionData.limit); | 
|  | 119 | +     | 
|  | 120 | +        // Apply page size limit | 
|  | 121 | +        query = query.limit(pageSize); | 
|  | 122 | +     | 
|  | 123 | +        // Execute the final query to get the page data | 
|  | 124 | +        const snapshot = await query.get(); | 
|  | 125 | +        const documents = snapshot.empty ? [] : snapshot.docs.map((i) => i.data()); | 
|  | 126 | +     | 
|  | 127 | +        // Return data object with totalCount and documents | 
|  | 128 | +        return { totalCount, documents }; | 
|  | 129 | +      }); | 
|  | 130 | +      return data; | 
|  | 131 | +    } | 
|  | 132 | + | 
|  | 133 | +    if (actionName === "FS.QueryFireStore") { | 
|  | 134 | +      const data = await withFirestoreCollection(async (ref) => { | 
|  | 135 | +        let query: FirebaseFirestore.Query<FirebaseFirestore.DocumentData> = ref; | 
|  | 136 | + | 
|  | 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)); | 
|  | 143 | +            } | 
|  | 144 | +            query = query.where(field, op as WhereFilterOp, value); | 
|  | 145 | +          } | 
| 108 | 146 |         } | 
| 109 |  | -        const snapshot = await (query || ref).get(); | 
|  | 147 | + | 
|  | 148 | +        // Execute the query and retrieve results | 
|  | 149 | +        const snapshot = await query.get(); | 
| 110 | 150 |         if (snapshot.empty) { | 
| 111 | 151 |           return []; | 
| 112 | 152 |         } | 
| 113 |  | -        return snapshot.docs.map((i) => i.data()); | 
|  | 153 | +        return snapshot.docs.map((doc) => doc.data()); | 
| 114 | 154 |       }); | 
| 115 | 155 |       return data; | 
| 116 | 156 |     } | 
|  | 157 | +     | 
| 117 | 158 | 
 | 
| 118 | 159 |     if (actionName === "FS.GetDocument") { | 
| 119 | 160 |       return await withFirestoreDoc(async (ref) => (await ref.get()).data()); | 
|  | 
0 commit comments