@@ -22,6 +22,255 @@ export const createLogger = jest.fn(() => ({
2222 fatal : jest . fn ( ) ,
2323} ) ) ;
2424
25- export const ObjectKernel = jest . fn ( ) ;
25+ class MockMetadataRegistry {
26+ private store = new Map < string , Map < string , any > > ( ) ;
27+
28+ register ( type : string , nameOrConfig : string | any , config ?: any ) : void {
29+ if ( ! this . store . has ( type ) ) {
30+ this . store . set ( type , new Map ( ) ) ;
31+ }
32+ const typeMap = this . store . get ( type ) ! ;
33+ let name : string ;
34+ let item : any ;
35+ if ( config ) {
36+ name = nameOrConfig as string ;
37+ item = config ;
38+ } else {
39+ item = nameOrConfig ;
40+ name = item . id || item . name ;
41+ }
42+ typeMap . set ( name , item ) ;
43+ }
44+
45+ get < T = any > ( type : string , id : string ) : T | undefined {
46+ const typeMap = this . store . get ( type ) ;
47+ const item = typeMap ?. get ( id ) ;
48+ return item ?. content as T ;
49+ }
50+
51+ list < T = any > ( type : string ) : T [ ] {
52+ const typeMap = this . store . get ( type ) ;
53+ if ( ! typeMap ) return [ ] ;
54+ return Array . from ( typeMap . values ( ) ) . map ( item => item . content as T ) ;
55+ }
56+
57+ unregister ( type : string , id : string ) : boolean {
58+ const typeMap = this . store . get ( type ) ;
59+ if ( ! typeMap ) return false ;
60+ return typeMap . delete ( id ) ;
61+ }
62+
63+ getTypes ( ) : string [ ] {
64+ return Array . from ( this . store . keys ( ) ) ;
65+ }
66+
67+ getEntry ( type : string , id : string ) : any | undefined {
68+ const typeMap = this . store . get ( type ) ;
69+ return typeMap ? typeMap . get ( id ) : undefined ;
70+ }
71+
72+ unregisterPackage ( packageName : string ) : void {
73+ for ( const [ _type , typeMap ] of this . store . entries ( ) ) {
74+ const toDelete : string [ ] = [ ] ;
75+ for ( const [ id , item ] of typeMap . entries ( ) ) {
76+ if ( item . packageName === packageName || item . package === packageName ) {
77+ toDelete . push ( id ) ;
78+ }
79+ }
80+ toDelete . forEach ( id => typeMap . delete ( id ) ) ;
81+ }
82+ }
83+ }
84+
85+ class MockHookManager {
86+ removePackage ( _packageName : string ) : void {
87+ // Mock implementation
88+ }
89+ clear ( ) : void {
90+ // Mock implementation
91+ }
92+ }
93+
94+ class MockActionManager {
95+ removePackage ( _packageName : string ) : void {
96+ // Mock implementation
97+ }
98+ clear ( ) : void {
99+ // Mock implementation
100+ }
101+ }
102+
103+ export class ObjectKernel {
104+ public ql : unknown = null ;
105+ public metadata : MockMetadataRegistry ;
106+ public hooks : MockHookManager ;
107+ public actions : MockActionManager ;
108+ private plugins : any [ ] = [ ] ;
109+ private driver : any = null ;
110+
111+ constructor ( plugins : any [ ] = [ ] ) {
112+ this . plugins = plugins ;
113+ this . metadata = new MockMetadataRegistry ( ) ;
114+ this . hooks = new MockHookManager ( ) ;
115+ this . actions = new MockActionManager ( ) ;
116+ }
117+
118+ setDriver ( driver : any ) : void {
119+ this . driver = driver ;
120+ }
121+
122+ async start ( ) : Promise < void > {
123+ for ( const plugin of this . plugins ) {
124+ if ( plugin . install ) {
125+ await plugin . install ( { engine : this } ) ;
126+ }
127+ }
128+ for ( const plugin of this . plugins ) {
129+ if ( plugin . onStart ) {
130+ await plugin . onStart ( { engine : this } ) ;
131+ }
132+ }
133+ }
134+
135+ async stop ( ) : Promise < void > {
136+ for ( const plugin of this . plugins ) {
137+ if ( plugin . onStop ) {
138+ await plugin . onStop ( { engine : this } ) ;
139+ }
140+ }
141+ }
142+
143+ getDriver ( ) : any {
144+ const driver = this . plugins . find ( p =>
145+ p . constructor . name ?. includes ( 'Driver' ) ||
146+ ( typeof p . find === 'function' && typeof p . create === 'function' )
147+ ) ;
148+ return driver || this . driver ;
149+ }
150+
151+ async seed ( ) : Promise < void > {
152+ // Mock implementation
153+ }
154+
155+ async find ( objectName : string , query : any ) : Promise < { value : Record < string , any > [ ] ; count : number } > {
156+ const driver = this . getDriver ( ) ;
157+ if ( driver ) {
158+ const normalizedQuery : any = { } ;
159+ if ( query . filters ) {
160+ normalizedQuery . where = query . filters ;
161+ } else if ( query . filter ) {
162+ normalizedQuery . where = query . filter ;
163+ } else if ( query . where ) {
164+ normalizedQuery . where = query . where ;
165+ }
166+ if ( query . fields ) {
167+ normalizedQuery . fields = query . fields ;
168+ }
169+ if ( query . sort ) {
170+ if ( Array . isArray ( query . sort ) && query . sort . length > 0 ) {
171+ const firstItem = query . sort [ 0 ] ;
172+ if ( firstItem !== undefined ) {
173+ if ( Array . isArray ( firstItem ) ) {
174+ normalizedQuery . orderBy = query . sort . map ( ( s : any ) => ( {
175+ field : s [ 0 ] ,
176+ order : s [ 1 ]
177+ } ) ) ;
178+ } else if ( typeof firstItem === 'object' ) {
179+ normalizedQuery . orderBy = query . sort . flatMap ( ( s : any ) =>
180+ Object . entries ( s ) . map ( ( [ field , order ] ) => ( {
181+ field,
182+ order : ( order === - 1 || order === 'desc' || order === 'DESC' ) ? 'desc' : 'asc'
183+ } ) )
184+ ) ;
185+ }
186+ }
187+ } else if ( query . sort ) {
188+ normalizedQuery . orderBy = query . sort ;
189+ }
190+ } else if ( query . orderBy ) {
191+ normalizedQuery . orderBy = query . orderBy ;
192+ }
193+ if ( query . limit !== undefined ) {
194+ normalizedQuery . limit = query . limit ;
195+ } else if ( query . top !== undefined ) {
196+ normalizedQuery . limit = query . top ;
197+ }
198+ if ( query . offset !== undefined ) {
199+ normalizedQuery . offset = query . offset ;
200+ } else if ( query . skip !== undefined ) {
201+ normalizedQuery . offset = query . skip ;
202+ }
203+ if ( query . aggregations ) {
204+ normalizedQuery . aggregate = query . aggregations . map ( ( agg : any ) => ( {
205+ func : agg . function ,
206+ field : agg . field ,
207+ alias : agg . alias
208+ } ) ) ;
209+ }
210+ if ( query . groupBy ) {
211+ normalizedQuery . groupBy = query . groupBy ;
212+ }
213+ const results = await driver . find ( objectName , normalizedQuery , { } ) ;
214+ return { value : results , count : results . length } ;
215+ }
216+ return { value : [ ] , count : 0 } ;
217+ }
218+
219+ async get ( objectName : string , id : string ) : Promise < Record < string , any > > {
220+ const driver = this . getDriver ( ) ;
221+ if ( driver ) {
222+ return await driver . findOne ( objectName , id , { } , { } ) ;
223+ }
224+ return { } ;
225+ }
226+
227+ async create ( objectName : string , data : any ) : Promise < Record < string , any > > {
228+ const driver = this . getDriver ( ) ;
229+ if ( driver ) {
230+ return await driver . create ( objectName , data , { } ) ;
231+ }
232+ return data ;
233+ }
234+
235+ async update ( objectName : string , id : string , data : any ) : Promise < Record < string , any > > {
236+ const driver = this . getDriver ( ) ;
237+ if ( driver ) {
238+ return await driver . update ( objectName , id , data , { } ) ;
239+ }
240+ return data ;
241+ }
242+
243+ async delete ( objectName : string , id : string ) : Promise < boolean > {
244+ const driver = this . getDriver ( ) ;
245+ if ( driver ) {
246+ const result = await driver . delete ( objectName , id , { } ) ;
247+ return result > 0 ;
248+ }
249+ return true ;
250+ }
251+
252+ getMetadata ( _objectName : string ) : any {
253+ return { } ;
254+ }
255+
256+ getView ( _objectName : string , _viewType ?: 'list' | 'form' ) : any {
257+ return null ;
258+ }
259+ }
260+
261+ export class ObjectStackProtocolImplementation { }
262+
263+ export interface PluginContext {
264+ engine : ObjectKernel ;
265+ }
266+
267+ export interface ObjectQLPlugin {
268+ name : string ;
269+ install ?: ( ctx : PluginContext ) => void | Promise < void > ;
270+ onStart ?: ( ctx : PluginContext ) => void | Promise < void > ;
271+ }
272+
273+ export { MockMetadataRegistry as MetadataRegistry } ;
274+
26275export const LiteKernel = jest . fn ( ) ;
27276export const createApiRegistryPlugin = jest . fn ( ) ;
0 commit comments