@@ -156,10 +156,47 @@ export class ObjectQLDataSource<T = any> implements DataSource<T> {
156156 if ( Array . isArray ( params . $filter ) ) {
157157 objectqlParams . filter = params . $filter as FilterExpression ;
158158 } else {
159- // Convert object format to FilterExpression format
160- objectqlParams . filter = Object . entries ( params . $filter ) . map (
161- ( [ key , value ] ) => [ key , '=' , value ] as [ string , string , any ]
162- ) as FilterExpression ;
159+ // Convert object format (including Mongo-like operator objects) to FilterExpression format
160+ const filterEntries = Object . entries ( params . $filter ) ;
161+ const filters : any [ ] = [ ] ;
162+
163+ const operatorMap : Record < string , string > = {
164+ $eq : '=' ,
165+ $ne : '!=' ,
166+ $gt : '>' ,
167+ $gte : '>=' ,
168+ $lt : '<' ,
169+ $lte : '<=' ,
170+ $in : 'in' ,
171+ $nin : 'not-in' ,
172+ } ;
173+
174+ for ( const [ key , value ] of filterEntries ) {
175+ const isPlainObject =
176+ value !== null &&
177+ typeof value === 'object' &&
178+ ! Array . isArray ( value ) ;
179+
180+ if ( isPlainObject ) {
181+ const opEntries = Object . entries ( value as Record < string , unknown > ) ;
182+ const hasDollarOperator = opEntries . some ( ( [ op ] ) => op . startsWith ( '$' ) ) ;
183+
184+ if ( hasDollarOperator ) {
185+ for ( const [ rawOp , opValue ] of opEntries ) {
186+ const mappedOp =
187+ operatorMap [ rawOp as keyof typeof operatorMap ] ??
188+ rawOp . replace ( / ^ \$ / , '' ) ;
189+ filters . push ( [ key , mappedOp , opValue ] ) ;
190+ }
191+ continue ;
192+ }
193+ }
194+
195+ // Fallback: treat as simple equality
196+ filters . push ( [ key , '=' , value ] ) ;
197+ }
198+
199+ objectqlParams . filter = filters as FilterExpression ;
163200 }
164201 }
165202
@@ -243,7 +280,7 @@ export class ObjectQLDataSource<T = any> implements DataSource<T> {
243280 return filtered as T ;
244281 }
245282
246- return response as T || null ;
283+ return response ? ( response as T ) : null ;
247284 } catch ( err : any ) {
248285 // Return null for not found errors
249286 if ( err . code === 'NOT_FOUND' || err . status === 404 ) {
@@ -333,7 +370,7 @@ export class ObjectQLDataSource<T = any> implements DataSource<T> {
333370 *
334371 * @param resource - Object name
335372 * @param operation - Operation type
336- * @param data - Bulk data or filters for update/delete
373+ * @param data - Bulk data (array of records for create/ update/delete)
337374 * @returns Promise resolving to operation results
338375 */
339376 async bulk (
@@ -346,38 +383,49 @@ export class ObjectQLDataSource<T = any> implements DataSource<T> {
346383 const response = await this . client . createMany < T > ( resource , data ) ;
347384 return response . items || [ ] ;
348385 } else if ( operation === 'update' ) {
349- // For bulk updates with SDK, we need filters and update data
350- // This is a limitation - the old API accepted array of records
351- // The new SDK requires filters + data
352- if ( Array . isArray ( data ) ) {
353- // If array of records is provided, we need to update them individually
354- // This is less efficient but maintains compatibility
355- const results : T [ ] = [ ] ;
356- for ( const item of data ) {
357- if ( '_id' in item && item . _id ) {
358- const updated = await this . client . update < T > ( resource , item . _id , item ) ;
359- results . push ( updated as T ) ;
360- }
386+ // Fallback implementation: iterate and call single-record update
387+ if ( ! Array . isArray ( data ) ) {
388+ throw new Error ( 'Bulk update requires array of records' ) ;
389+ }
390+
391+ const results : T [ ] = [ ] ;
392+ for ( const item of data ) {
393+ const record : any = item as any ;
394+ const id = record ?. id ?? record ?. _id ;
395+ if ( id === undefined || id === null ) {
396+ throw new Error (
397+ 'Bulk update requires each item to include an `id` or `_id` field.'
398+ ) ;
399+ }
400+ // Do not send id as part of the update payload
401+ const { id : _omitId , _id : _omitUnderscore , ...updateData } = record ;
402+ const updated = await this . client . update < T > ( resource , id , updateData ) ;
403+ if ( updated !== undefined && updated !== null ) {
404+ results . push ( updated as T ) ;
361405 }
362- return results ;
363- } else {
364- throw new Error ( 'Bulk update requires array of records with _id field' ) ;
365406 }
407+ return results ;
366408 } else if ( operation === 'delete' ) {
367- // For bulk deletes with SDK, similar approach
368- if ( Array . isArray ( data ) ) {
369- // Delete each record individually
370- const results : T [ ] = [ ] ;
371- for ( const item of data ) {
372- if ( '_id' in item && item . _id ) {
373- await this . client . delete ( resource , item . _id ) ;
374- results . push ( item as T ) ;
375- }
409+ // Fallback implementation: iterate and call single-record delete
410+ if ( ! Array . isArray ( data ) ) {
411+ throw new Error ( 'Bulk delete requires array of records or IDs' ) ;
412+ }
413+
414+ for ( const item of data ) {
415+ const record : any = item as any ;
416+ // Support both direct ID values and objects with id/_id field
417+ const id = typeof record === 'object'
418+ ? ( record ?. id ?? record ?. _id )
419+ : record ;
420+ if ( id === undefined || id === null ) {
421+ throw new Error (
422+ 'Bulk delete requires each item to include an `id` or `_id` field or be an id value.'
423+ ) ;
376424 }
377- return results ;
378- } else {
379- throw new Error ( 'Bulk delete requires array of records with _id field' ) ;
425+ await this . client . delete ( resource , id ) ;
380426 }
427+ // For delete operations, we return an empty array by convention
428+ return [ ] ;
381429 }
382430
383431 throw new Error ( `Unknown bulk operation: ${ operation } ` ) ;
0 commit comments