@@ -20,7 +20,18 @@ export class ObjectQL {
2020
2121 async connect ( ) { }
2222 async disconnect ( ) { }
23- async init ( ) { }
23+ async init ( ) {
24+ // Initialize drivers (connect + sync schema)
25+ for ( const [ _name , driver ] of this . drivers ) {
26+ if ( driver . connect ) {
27+ await driver . connect ( ) ;
28+ }
29+ if ( driver . init ) {
30+ const objects = SchemaRegistry . getAllObjects ( ) ;
31+ await driver . init ( objects ) ;
32+ }
33+ }
34+ }
2435
2536 registerDriver ( driver : any , isDefault : boolean = false ) {
2637 if ( ! driver . name ) {
@@ -31,6 +42,18 @@ export class ObjectQL {
3142 this . defaultDriver = driver . name ;
3243 }
3344 }
45+
46+ datasource ( name : string ) : any {
47+ const driver = this . drivers . get ( name ) ;
48+ if ( ! driver ) {
49+ throw new Error ( `[ObjectQL] Datasource '${ name } ' not found` ) ;
50+ }
51+ return driver ;
52+ }
53+
54+ getDriverByName ( name : string ) : any {
55+ return this . drivers . get ( name ) ;
56+ }
3457
3558 registerObject ( schema : any , packageId : string = '__runtime__' , namespace ?: string ) : string {
3659 // Auto-assign field names from keys
@@ -68,6 +91,10 @@ export class ObjectQL {
6891 this . hooks . get ( event ) ! . push ( { handler, options } ) ;
6992 }
7093
94+ on ( event : string , objectName : string , handler : any , packageId ?: string ) {
95+ this . registerHook ( event , handler , { object : objectName , packageId } ) ;
96+ }
97+
7198 registerMiddleware ( fn : any , options ?: { object ?: string } ) {
7299 this . middlewares . push ( { fn, object : options ?. object } ) ;
73100 }
@@ -128,25 +155,101 @@ export class ObjectQL {
128155 } ) ;
129156 return opCtx . result ;
130157 } ,
158+ create : async ( data : any ) => {
159+ const driver = this . drivers . get ( this . defaultDriver || this . drivers . keys ( ) . next ( ) . value ) ;
160+ const opCtx = { object : name , operation : 'insert' , data, context : options , result : undefined as any } ;
161+ await this . executeWithMiddleware ( opCtx , async ( ) => {
162+ const hookContext : any = {
163+ object : name , event : 'beforeCreate' ,
164+ input : { data : opCtx . data } , session : options ,
165+ data : opCtx . data , user : options . userId ? { id : options . userId } : options . user
166+ } ;
167+ await this . triggerHooks ( 'beforeCreate' , hookContext ) ;
168+ const finalData = hookContext . data || hookContext . input . data ;
169+ const result = driver ?. create ? await driver . create ( name , finalData , options ) : finalData ;
170+ hookContext . event = 'afterCreate' ;
171+ hookContext . result = result ;
172+ await this . triggerHooks ( 'afterCreate' , hookContext ) ;
173+ return hookContext . result ;
174+ } ) ;
175+ return opCtx . result ;
176+ } ,
131177 insert : async ( data : any ) => {
132178 const driver = this . drivers . get ( this . defaultDriver || this . drivers . keys ( ) . next ( ) . value ) ;
133- if ( driver && driver . insert ) {
134- return driver . insert ( name , data ) ;
135- }
136- return data ;
179+ const opCtx = { object : name , operation : 'insert' , data, context : options , result : undefined as any } ;
180+ await this . executeWithMiddleware ( opCtx , async ( ) => {
181+ const hookContext : any = {
182+ object : name , event : 'beforeCreate' ,
183+ input : { data : opCtx . data } , session : options ,
184+ data : opCtx . data , user : options . userId ? { id : options . userId } : options . user
185+ } ;
186+ await this . triggerHooks ( 'beforeCreate' , hookContext ) ;
187+ const finalData = hookContext . data || hookContext . input . data ;
188+ const result = driver ?. create ? await driver . create ( name , finalData , options )
189+ : driver ?. insert ? await driver . insert ( name , finalData )
190+ : finalData ;
191+ hookContext . event = 'afterCreate' ;
192+ hookContext . result = result ;
193+ await this . triggerHooks ( 'afterCreate' , hookContext ) ;
194+ return hookContext . result ;
195+ } ) ;
196+ return opCtx . result ;
137197 } ,
138198 update : async ( id : string , data : any ) => {
139199 const driver = this . drivers . get ( this . defaultDriver || this . drivers . keys ( ) . next ( ) . value ) ;
140- if ( driver && driver . update ) {
141- return driver . update ( name , id , data ) ;
142- }
143- return data ;
200+ const opCtx = { object : name , operation : 'update' , data, context : options , result : undefined as any } ;
201+ await this . executeWithMiddleware ( opCtx , async ( ) => {
202+ // Fetch previous data for hooks that need it
203+ let previousData : any ;
204+ if ( driver ?. findOne ) {
205+ try { previousData = await driver . findOne ( name , { _id : id } ) ; } catch ( _e ) { /* ignore */ }
206+ }
207+ const hookContext : any = {
208+ object : name , event : 'beforeUpdate' ,
209+ input : { id, data : opCtx . data } , session : options ,
210+ data : opCtx . data , previousData, user : options . userId ? { id : options . userId } : options . user
211+ } ;
212+ await this . triggerHooks ( 'beforeUpdate' , hookContext ) ;
213+ const finalData = hookContext . data || hookContext . input . data ;
214+ const result = driver ?. update ? await driver . update ( name , id , finalData , options ) : finalData ;
215+ hookContext . event = 'afterUpdate' ;
216+ hookContext . result = result ;
217+ await this . triggerHooks ( 'afterUpdate' , hookContext ) ;
218+ return hookContext . result ;
219+ } ) ;
220+ return opCtx . result ;
144221 } ,
145222 delete : async ( id : string ) => {
146223 const driver = this . drivers . get ( this . defaultDriver || this . drivers . keys ( ) . next ( ) . value ) ;
147- if ( driver && driver . delete ) {
148- return driver . delete ( name , id ) ;
224+ const opCtx = { object : name , operation : 'delete' , context : options , result : undefined as any } ;
225+ await this . executeWithMiddleware ( opCtx , async ( ) => {
226+ // Fetch current data for hooks that need it
227+ let previousData : any ;
228+ if ( driver ?. findOne ) {
229+ try { previousData = await driver . findOne ( name , { _id : id } ) ; } catch ( _e ) { /* ignore */ }
230+ }
231+ const hookContext : any = {
232+ object : name , event : 'beforeDelete' ,
233+ input : { id } , session : options ,
234+ data : previousData , previousData, user : options . userId ? { id : options . userId } : options . user
235+ } ;
236+ await this . triggerHooks ( 'beforeDelete' , hookContext ) ;
237+ const result = driver ?. delete ? await driver . delete ( name , id ) : true ;
238+ hookContext . event = 'afterDelete' ;
239+ hookContext . result = result ;
240+ await this . triggerHooks ( 'afterDelete' , hookContext ) ;
241+ return hookContext . result ;
242+ } ) ;
243+ return opCtx . result ;
244+ } ,
245+ count : async ( filter ?: any ) => {
246+ const driver = this . drivers . get ( this . defaultDriver || this . drivers . keys ( ) . next ( ) . value ) ;
247+ if ( driver ?. count ) {
248+ return driver . count ( name , filter ) ;
149249 }
250+ // Fallback: use find and count
251+ const results = driver ?. find ? await driver . find ( name , filter ) : [ ] ;
252+ return Array . isArray ( results ) ? results . length : 0 ;
150253 }
151254 } )
152255 } ;
0 commit comments