@objectstack/plugin-msw 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @objectstack/plugin-msw
2
2
 
3
+ ## 0.8.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 555e6a7: Refactor: Deprecated View Storage protocol in favor of Metadata Views.
8
+
9
+ - **BREAKING**: Removed `view-storage.zod.ts` and `ViewStorage` related types from `@objectstack/spec`.
10
+ - **BREAKING**: Removed `createView`, `updateView`, `deleteView`, `listViews` from `ObjectStackProtocol` interface.
11
+ - **BREAKING**: Removed in-memory View Storage implementation from `@objectstack/objectql`.
12
+ - **UPDATE**: `@objectstack/plugin-msw` now dynamically loads `@objectstack/objectql` to avoid hard dependencies.
13
+
14
+ - Updated dependencies [555e6a7]
15
+ - @objectstack/spec@0.8.2
16
+ - @objectstack/objectql@0.8.2
17
+ - @objectstack/runtime@0.8.2
18
+ - @objectstack/types@0.8.2
19
+
20
+ ## 0.8.1
21
+
22
+ ### Patch Changes
23
+
24
+ - @objectstack/spec@0.8.1
25
+ - @objectstack/types@0.8.1
26
+ - @objectstack/objectql@0.8.1
27
+ - @objectstack/runtime@0.8.1
28
+
3
29
  ## 1.0.0
4
30
 
5
31
  ### Minor Changes
@@ -1,6 +1,5 @@
1
1
  import { http, HttpResponse, passthrough } from 'msw';
2
2
  import { setupWorker } from 'msw/browser';
3
- import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
4
3
  /**
5
4
  * ObjectStack Server Mock - Provides mock database functionality
6
5
  */
@@ -172,13 +171,40 @@ export class MSWPlugin {
172
171
  async start(ctx) {
173
172
  ctx.logger.debug('Starting MSW plugin');
174
173
  try {
175
- const dataEngine = ctx.getService('objectql');
176
- this.protocol = new ObjectStackProtocolImplementation(dataEngine);
177
- ctx.logger.debug('Protocol implementation created');
174
+ // 1. Try to get existing protocol service
175
+ try {
176
+ this.protocol = ctx.getService('protocol');
177
+ ctx.logger.debug('Protocol service found from context');
178
+ }
179
+ catch (e) {
180
+ // Ignore, will try to create default implementation
181
+ }
182
+ // 2. If not found, try to instantiate default implementation dynamically
183
+ if (!this.protocol) {
184
+ try {
185
+ const dataEngine = ctx.getService('objectql');
186
+ // Dynamically import ObjectStackProtocolImplementation to avoid hard dependency
187
+ const { ObjectStackProtocolImplementation } = await import('@objectstack/objectql');
188
+ this.protocol = new ObjectStackProtocolImplementation(dataEngine);
189
+ ctx.logger.debug('Protocol implementation created dynamically');
190
+ }
191
+ catch (e) {
192
+ if (e.code === 'ERR_MODULE_NOT_FOUND') {
193
+ ctx.logger.warn('Module @objectstack/objectql not found. Protocol not initialized.');
194
+ }
195
+ else {
196
+ throw e;
197
+ }
198
+ }
199
+ }
200
+ if (!this.protocol) {
201
+ // Without a protocol, MSW can't serve data APIs
202
+ ctx.logger.warn('No ObjectStackProtocol service available. MSW will only serve static/custom handlers if configured.');
203
+ }
178
204
  }
179
205
  catch (e) {
180
206
  ctx.logger.error('Failed to initialize protocol', e);
181
- throw new Error('[MSWPlugin] Failed to initialize protocol (missing objectql service?)');
207
+ throw new Error('[MSWPlugin] Failed to initialize protocol');
182
208
  }
183
209
  this.setupHandlers(ctx);
184
210
  await this.startWorker(ctx);
@@ -194,7 +220,11 @@ export class MSWPlugin {
194
220
  */
195
221
  setupHandlers(ctx) {
196
222
  if (!this.protocol) {
197
- throw new Error('[MSWPlugin] Protocol not initialized');
223
+ ctx.logger.warn('[MSWPlugin] Protocol not initialized. Skipping default API handlers.');
224
+ this.handlers = [
225
+ ...(this.options.customHandlers || [])
226
+ ];
227
+ return;
198
228
  }
199
229
  const protocol = this.protocol;
200
230
  // Initialize ObjectStackServer with structured logger
@@ -402,109 +432,6 @@ export class MSWPlugin {
402
432
  return HttpResponse.json({ error: message }, { status: 404 });
403
433
  }
404
434
  }),
405
- // View Storage Operations
406
- http.post(`${baseUrl}/ui/views`, async ({ request }) => {
407
- try {
408
- const body = await request.json();
409
- const result = await protocol.createView(body);
410
- if (result.success) {
411
- return HttpResponse.json(result, { status: 201 });
412
- }
413
- else {
414
- return HttpResponse.json(result, { status: 400 });
415
- }
416
- }
417
- catch (error) {
418
- const message = error instanceof Error ? error.message : 'Unknown error';
419
- return HttpResponse.json({ success: false, error: { code: 'internal_error', message } }, { status: 500 });
420
- }
421
- }),
422
- http.get(`${baseUrl}/ui/views/:id`, async ({ params }) => {
423
- try {
424
- const result = await protocol.getView({ id: params.id });
425
- if (result.success) {
426
- return HttpResponse.json(result);
427
- }
428
- else {
429
- return HttpResponse.json(result, { status: 404 });
430
- }
431
- }
432
- catch (error) {
433
- const message = error instanceof Error ? error.message : 'Unknown error';
434
- return HttpResponse.json({ success: false, error: { code: 'internal_error', message } }, { status: 500 });
435
- }
436
- }),
437
- http.get(`${baseUrl}/ui/views`, async ({ request }) => {
438
- try {
439
- const url = new URL(request.url);
440
- const queryRequest = {};
441
- if (url.searchParams.get('object'))
442
- queryRequest.object = url.searchParams.get('object');
443
- if (url.searchParams.get('type'))
444
- queryRequest.type = url.searchParams.get('type');
445
- if (url.searchParams.get('visibility'))
446
- queryRequest.visibility = url.searchParams.get('visibility');
447
- if (url.searchParams.get('createdBy'))
448
- queryRequest.createdBy = url.searchParams.get('createdBy');
449
- if (url.searchParams.get('isDefault'))
450
- queryRequest.isDefault = url.searchParams.get('isDefault') === 'true';
451
- // Parse numeric parameters with validation
452
- const limitParam = url.searchParams.get('limit');
453
- const offsetParam = url.searchParams.get('offset');
454
- if (limitParam) {
455
- const limit = parseInt(limitParam, 10);
456
- if (!isNaN(limit) && limit > 0)
457
- queryRequest.limit = limit;
458
- }
459
- if (offsetParam) {
460
- const offset = parseInt(offsetParam, 10);
461
- if (!isNaN(offset) && offset >= 0)
462
- queryRequest.offset = offset;
463
- }
464
- const result = await protocol.listViews(queryRequest);
465
- return HttpResponse.json(result);
466
- }
467
- catch (error) {
468
- const message = error instanceof Error ? error.message : 'Unknown error';
469
- return HttpResponse.json({ success: false, error: { code: 'internal_error', message } }, { status: 500 });
470
- }
471
- }),
472
- http.patch(`${baseUrl}/ui/views/:id`, async ({ params, request }) => {
473
- try {
474
- const body = await request.json();
475
- // Merge body with id parameter, ensuring body is an object
476
- const updateData = (typeof body === 'object' && body !== null)
477
- ? { ...body, id: params.id }
478
- : { id: params.id };
479
- const result = await protocol.updateView(updateData);
480
- if (result.success) {
481
- return HttpResponse.json(result);
482
- }
483
- else {
484
- const statusCode = result.error?.code === 'resource_not_found' ? 404 : 400;
485
- return HttpResponse.json(result, { status: statusCode });
486
- }
487
- }
488
- catch (error) {
489
- const message = error instanceof Error ? error.message : 'Unknown error';
490
- return HttpResponse.json({ success: false, error: { code: 'internal_error', message } }, { status: 500 });
491
- }
492
- }),
493
- http.delete(`${baseUrl}/ui/views/:id`, async ({ params }) => {
494
- try {
495
- const result = await protocol.deleteView({ id: params.id });
496
- if (result.success) {
497
- return HttpResponse.json(result);
498
- }
499
- else {
500
- return HttpResponse.json(result, { status: 404 });
501
- }
502
- }
503
- catch (error) {
504
- const message = error instanceof Error ? error.message : 'Unknown error';
505
- return HttpResponse.json({ success: false, error: { code: 'internal_error', message } }, { status: 500 });
506
- }
507
- }),
508
435
  // Add custom handlers
509
436
  ...(this.options.customHandlers || [])
510
437
  ];
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "@objectstack/plugin-msw",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "MSW (Mock Service Worker) Plugin for ObjectStack Runtime",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "dependencies": {
8
8
  "msw": "^2.0.0",
9
- "@objectstack/spec": "0.8.0",
10
- "@objectstack/types": "0.8.0",
11
- "@objectstack/objectql": "0.8.0"
9
+ "@objectstack/spec": "0.8.2",
10
+ "@objectstack/types": "0.8.2",
11
+ "@objectstack/objectql": "0.8.2"
12
12
  },
13
13
  "devDependencies": {
14
14
  "@types/node": "^25.1.0",
15
15
  "typescript": "^5.0.0",
16
- "@objectstack/runtime": "0.8.0"
16
+ "@objectstack/runtime": "0.8.2"
17
17
  },
18
18
  "peerDependencies": {
19
- "@objectstack/runtime": "^0.8.0"
19
+ "@objectstack/runtime": "^0.8.2"
20
20
  },
21
21
  "scripts": {
22
22
  "build": "tsc"
package/src/msw-plugin.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  ObjectKernel,
7
7
  IDataEngine
8
8
  } from '@objectstack/runtime';
9
- import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
9
+ // import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
10
10
  import { ObjectStackProtocol } from '@objectstack/spec/api';
11
11
  // import { IDataEngine } from '@objectstack/core';
12
12
 
@@ -221,12 +221,39 @@ export class MSWPlugin implements Plugin {
221
221
  ctx.logger.debug('Starting MSW plugin');
222
222
 
223
223
  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
+
227
254
  } catch (e) {
228
255
  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');
230
257
  }
231
258
 
232
259
  this.setupHandlers(ctx);
@@ -245,7 +272,11 @@ export class MSWPlugin implements Plugin {
245
272
  */
246
273
  private setupHandlers(ctx: PluginContext) {
247
274
  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;
249
280
  }
250
281
 
251
282
  const protocol = this.protocol;
@@ -488,101 +519,6 @@ export class MSWPlugin implements Plugin {
488
519
  }
489
520
  }),
490
521
 
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
-
586
522
  // Add custom handlers
587
523
  ...(this.options.customHandlers || [])
588
524
  ];