Skip to content

Commit 720c09e

Browse files
committed
feat: enhance MSWPlugin to dynamically load protocol implementation and remove legacy view storage operations
1 parent f2c8f6e commit 720c09e

File tree

1 file changed

+37
-101
lines changed

1 file changed

+37
-101
lines changed

packages/plugins/plugin-msw/src/msw-plugin.ts

Lines changed: 37 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
ObjectKernel,
77
IDataEngine
88
} from '@objectstack/runtime';
9-
import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
9+
// import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
1010
import { 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

Comments
 (0)