66 ObjectKernel ,
77 IDataEngine
88} from '@objectstack/runtime' ;
9- import { ObjectStackProtocolImplementation } from '@objectstack/objectql' ;
9+ // import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
1010import { ObjectStackProtocol } from '@objectstack/spec/api' ;
1111// import { IDataEngine } from '@objectstack/core';
1212
@@ -221,12 +221,39 @@ export class MSWPlugin implements Plugin {
221221 ctx . logger . debug ( 'Starting MSW plugin' ) ;
222222
223223 try {
224- const dataEngine = ctx . getService < IDataEngine > ( 'objectql' ) ;
225- this . protocol = new ObjectStackProtocolImplementation ( dataEngine ) ;
226- ctx . logger . debug ( 'Protocol implementation created' ) ;
224+ // 1. Try to get existing protocol service
225+ try {
226+ this . protocol = ctx . getService < ObjectStackProtocol > ( 'protocol' ) ;
227+ ctx . logger . debug ( 'Protocol service found from context' ) ;
228+ } catch ( e ) {
229+ // Ignore, will try to create default implementation
230+ }
231+
232+ // 2. If not found, try to instantiate default implementation dynamically
233+ if ( ! this . protocol ) {
234+ try {
235+ const dataEngine = ctx . getService < IDataEngine > ( 'objectql' ) ;
236+ // Dynamically import ObjectStackProtocolImplementation to avoid hard dependency
237+ const { ObjectStackProtocolImplementation } = await import ( '@objectstack/objectql' ) ;
238+ this . protocol = new ObjectStackProtocolImplementation ( dataEngine ) ;
239+ ctx . logger . debug ( 'Protocol implementation created dynamically' ) ;
240+ } catch ( e : any ) {
241+ if ( e . code === 'ERR_MODULE_NOT_FOUND' ) {
242+ ctx . logger . warn ( 'Module @objectstack/objectql not found. Protocol not initialized.' ) ;
243+ } else {
244+ throw e ;
245+ }
246+ }
247+ }
248+
249+ if ( ! this . protocol ) {
250+ // Without a protocol, MSW can't serve data APIs
251+ ctx . logger . warn ( 'No ObjectStackProtocol service available. MSW will only serve static/custom handlers if configured.' ) ;
252+ }
253+
227254 } catch ( e ) {
228255 ctx . logger . error ( 'Failed to initialize protocol' , e as Error ) ;
229- throw new Error ( '[MSWPlugin] Failed to initialize protocol (missing objectql service?) ' ) ;
256+ throw new Error ( '[MSWPlugin] Failed to initialize protocol' ) ;
230257 }
231258
232259 this . setupHandlers ( ctx ) ;
@@ -245,7 +272,11 @@ export class MSWPlugin implements Plugin {
245272 */
246273 private setupHandlers ( ctx : PluginContext ) {
247274 if ( ! this . protocol ) {
248- throw new Error ( '[MSWPlugin] Protocol not initialized' ) ;
275+ ctx . logger . warn ( '[MSWPlugin] Protocol not initialized. Skipping default API handlers.' ) ;
276+ this . handlers = [
277+ ...( this . options . customHandlers || [ ] )
278+ ] ;
279+ return ;
249280 }
250281
251282 const protocol = this . protocol ;
@@ -488,101 +519,6 @@ export class MSWPlugin implements Plugin {
488519 }
489520 } ) ,
490521
491- // View Storage Operations
492- http . post ( `${ baseUrl } /ui/views` , async ( { request } ) => {
493- try {
494- const body = await request . json ( ) ;
495- const result = await protocol . createView ( body as any ) ;
496- if ( result . success ) {
497- return HttpResponse . json ( result , { status : 201 } ) ;
498- } else {
499- return HttpResponse . json ( result , { status : 400 } ) ;
500- }
501- } catch ( error ) {
502- const message = error instanceof Error ? error . message : 'Unknown error' ;
503- return HttpResponse . json ( { success : false , error : { code : 'internal_error' , message } } , { status : 500 } ) ;
504- }
505- } ) ,
506-
507- http . get ( `${ baseUrl } /ui/views/:id` , async ( { params } ) => {
508- try {
509- const result = await protocol . getView ( { id : params . id as string } ) ;
510- if ( result . success ) {
511- return HttpResponse . json ( result ) ;
512- } else {
513- return HttpResponse . json ( result , { status : 404 } ) ;
514- }
515- } catch ( error ) {
516- const message = error instanceof Error ? error . message : 'Unknown error' ;
517- return HttpResponse . json ( { success : false , error : { code : 'internal_error' , message } } , { status : 500 } ) ;
518- }
519- } ) ,
520-
521- http . get ( `${ baseUrl } /ui/views` , async ( { request } ) => {
522- try {
523- const url = new URL ( request . url ) ;
524- const queryRequest : any = { } ;
525- if ( url . searchParams . get ( 'object' ) ) queryRequest . object = url . searchParams . get ( 'object' ) ;
526- if ( url . searchParams . get ( 'type' ) ) queryRequest . type = url . searchParams . get ( 'type' ) ;
527- if ( url . searchParams . get ( 'visibility' ) ) queryRequest . visibility = url . searchParams . get ( 'visibility' ) ;
528- if ( url . searchParams . get ( 'createdBy' ) ) queryRequest . createdBy = url . searchParams . get ( 'createdBy' ) ;
529- if ( url . searchParams . get ( 'isDefault' ) ) queryRequest . isDefault = url . searchParams . get ( 'isDefault' ) === 'true' ;
530-
531- // Parse numeric parameters with validation
532- const limitParam = url . searchParams . get ( 'limit' ) ;
533- const offsetParam = url . searchParams . get ( 'offset' ) ;
534- if ( limitParam ) {
535- const limit = parseInt ( limitParam , 10 ) ;
536- if ( ! isNaN ( limit ) && limit > 0 ) queryRequest . limit = limit ;
537- }
538- if ( offsetParam ) {
539- const offset = parseInt ( offsetParam , 10 ) ;
540- if ( ! isNaN ( offset ) && offset >= 0 ) queryRequest . offset = offset ;
541- }
542-
543- const result = await protocol . listViews ( queryRequest ) ;
544- return HttpResponse . json ( result ) ;
545- } catch ( error ) {
546- const message = error instanceof Error ? error . message : 'Unknown error' ;
547- return HttpResponse . json ( { success : false , error : { code : 'internal_error' , message } } , { status : 500 } ) ;
548- }
549- } ) ,
550-
551- http . patch ( `${ baseUrl } /ui/views/:id` , async ( { params, request } ) => {
552- try {
553- const body = await request . json ( ) as any ;
554- // Merge body with id parameter, ensuring body is an object
555- const updateData = ( typeof body === 'object' && body !== null )
556- ? { ...body , id : params . id as string }
557- : { id : params . id as string } ;
558-
559- const result = await protocol . updateView ( updateData as any ) ;
560- if ( result . success ) {
561- return HttpResponse . json ( result ) ;
562- } else {
563- const statusCode = result . error ?. code === 'resource_not_found' ? 404 : 400 ;
564- return HttpResponse . json ( result , { status : statusCode } ) ;
565- }
566- } catch ( error ) {
567- const message = error instanceof Error ? error . message : 'Unknown error' ;
568- return HttpResponse . json ( { success : false , error : { code : 'internal_error' , message } } , { status : 500 } ) ;
569- }
570- } ) ,
571-
572- http . delete ( `${ baseUrl } /ui/views/:id` , async ( { params } ) => {
573- try {
574- const result = await protocol . deleteView ( { id : params . id as string } ) ;
575- if ( result . success ) {
576- return HttpResponse . json ( result ) ;
577- } else {
578- return HttpResponse . json ( result , { status : 404 } ) ;
579- }
580- } catch ( error ) {
581- const message = error instanceof Error ? error . message : 'Unknown error' ;
582- return HttpResponse . json ( { success : false , error : { code : 'internal_error' , message } } , { status : 500 } ) ;
583- }
584- } ) ,
585-
586522 // Add custom handlers
587523 ...( this . options . customHandlers || [ ] )
588524 ] ;
0 commit comments