11import { QueryAST , HookContext } from '@objectstack/spec/data' ;
22import { ObjectStackManifest } from '@objectstack/spec/system' ;
33import { DriverInterface , DriverOptions } from '@objectstack/spec/system' ;
4+ import { IDataEngine , DataEngineQueryOptions } from '@objectstack/spec/system' ;
45import { SchemaRegistry } from './registry' ;
56
67// Export Registry for consumers
@@ -20,8 +21,10 @@ export interface PluginContext {
2021
2122/**
2223 * ObjectQL Engine
24+ *
25+ * Implements the IDataEngine interface for data persistence.
2326 */
24- export class ObjectQL {
27+ export class ObjectQL implements IDataEngine {
2528 private drivers = new Map < string , DriverInterface > ( ) ;
2629 private defaultDriver : string | null = null ;
2730
@@ -211,27 +214,57 @@ export class ObjectQL {
211214 }
212215
213216 // ============================================
214- // Data Access Methods
217+ // Data Access Methods (IDataEngine Interface)
215218 // ============================================
216219
217- async find ( object : string , query : any = { } , options ?: DriverOptions ) {
220+ /**
221+ * Find records matching a query (IDataEngine interface)
222+ *
223+ * @param object - Object name
224+ * @param query - Query options (IDataEngine format)
225+ * @returns Promise resolving to array of records
226+ */
227+ async find ( object : string , query ?: DataEngineQueryOptions ) : Promise < any [ ] > {
218228 const driver = this . getDriver ( object ) ;
219229
220- // Normalize QueryAST
221- let ast : QueryAST ;
222- if ( query . where || query . fields || query . orderBy || query . limit ) {
223- ast = { object, ...query } as QueryAST ;
224- } else {
225- ast = { object, where : query } as QueryAST ;
230+ // Convert DataEngineQueryOptions to QueryAST
231+ let ast : QueryAST = { object } ;
232+
233+ if ( query ) {
234+ // Map DataEngineQueryOptions to QueryAST
235+ if ( query . filter ) {
236+ ast . where = query . filter ;
237+ }
238+ if ( query . select ) {
239+ ast . fields = query . select ;
240+ }
241+ if ( query . sort ) {
242+ // Convert sort Record to orderBy array
243+ // sort: { createdAt: -1, name: 'asc' } => orderBy: [{ field: 'createdAt', order: 'desc' }, { field: 'name', order: 'asc' }]
244+ ast . orderBy = Object . entries ( query . sort ) . map ( ( [ field , order ] ) => ( {
245+ field,
246+ order : ( order === - 1 || order === 'desc' ) ? 'desc' : 'asc'
247+ } ) ) ;
248+ }
249+ // Handle both limit and top (top takes precedence)
250+ if ( query . top !== undefined ) {
251+ ast . limit = query . top ;
252+ } else if ( query . limit !== undefined ) {
253+ ast . limit = query . limit ;
254+ }
255+ if ( query . skip !== undefined ) {
256+ ast . offset = query . skip ;
257+ }
226258 }
227259
260+ // Set default limit if not specified
228261 if ( ast . limit === undefined ) ast . limit = 100 ;
229262
230263 // Trigger Before Hook
231264 const hookContext : HookContext = {
232265 object,
233266 event : 'beforeFind' ,
234- input : { ast, options } , // Hooks can modify AST here
267+ input : { ast, options : undefined } ,
235268 ql : this
236269 } ;
237270 await this . triggerHooks ( 'beforeFind' , hookContext ) ;
@@ -275,7 +308,14 @@ export class ObjectQL {
275308 return driver . findOne ( object , ast , options ) ;
276309 }
277310
278- async insert ( object : string , data : Record < string , any > , options ?: DriverOptions ) {
311+ /**
312+ * Insert a new record (IDataEngine interface)
313+ *
314+ * @param object - Object name
315+ * @param data - Data to insert
316+ * @returns Promise resolving to the created record
317+ */
318+ async insert ( object : string , data : any ) : Promise < any > {
279319 const driver = this . getDriver ( object ) ;
280320
281321 // 1. Get Schema
@@ -290,7 +330,7 @@ export class ObjectQL {
290330 const hookContext : HookContext = {
291331 object,
292332 event : 'beforeInsert' ,
293- input : { data, options } ,
333+ input : { data, options : undefined } ,
294334 ql : this
295335 } ;
296336 await this . triggerHooks ( 'beforeInsert' , hookContext ) ;
@@ -306,13 +346,21 @@ export class ObjectQL {
306346 return hookContext . result ;
307347 }
308348
309- async update ( object : string , id : string | number , data : Record < string , any > , options ?: DriverOptions ) {
349+ /**
350+ * Update a record by ID (IDataEngine interface)
351+ *
352+ * @param object - Object name
353+ * @param id - Record ID
354+ * @param data - Updated data
355+ * @returns Promise resolving to the updated record
356+ */
357+ async update ( object : string , id : any , data : any ) : Promise < any > {
310358 const driver = this . getDriver ( object ) ;
311359
312360 const hookContext : HookContext = {
313361 object,
314362 event : 'beforeUpdate' ,
315- input : { id, data, options } ,
363+ input : { id, data, options : undefined } ,
316364 ql : this
317365 } ;
318366 await this . triggerHooks ( 'beforeUpdate' , hookContext ) ;
@@ -326,13 +374,20 @@ export class ObjectQL {
326374 return hookContext . result ;
327375 }
328376
329- async delete ( object : string , id : string | number , options ?: DriverOptions ) {
377+ /**
378+ * Delete a record by ID (IDataEngine interface)
379+ *
380+ * @param object - Object name
381+ * @param id - Record ID
382+ * @returns Promise resolving to true if deleted, false otherwise
383+ */
384+ async delete ( object : string , id : any ) : Promise < boolean > {
330385 const driver = this . getDriver ( object ) ;
331386
332387 const hookContext : HookContext = {
333388 object,
334389 event : 'beforeDelete' ,
335- input : { id, options } ,
390+ input : { id, options : undefined } ,
336391 ql : this
337392 } ;
338393 await this . triggerHooks ( 'beforeDelete' , hookContext ) ;
@@ -343,6 +398,7 @@ export class ObjectQL {
343398 hookContext . result = result ;
344399 await this . triggerHooks ( 'afterDelete' , hookContext ) ;
345400
401+ // Driver.delete() already returns boolean per DriverInterface spec
346402 return hookContext . result ;
347403 }
348404}
0 commit comments