@objectstack/plugin-msw 0.6.1 → 0.7.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,27 @@
1
1
  # @objectstack/plugin-msw
2
2
 
3
+ ## 0.7.2
4
+
5
+ ### Patch Changes
6
+
7
+ - fb41cc0: Patch release: Updated documentation and JSON schemas
8
+ - Updated dependencies [fb41cc0]
9
+ - @objectstack/spec@0.7.2
10
+ - @objectstack/types@0.7.2
11
+ - @objectstack/objectql@0.7.2
12
+ - @objectstack/runtime@0.7.2
13
+
14
+ ## 0.7.1
15
+
16
+ ### Patch Changes
17
+
18
+ - Patch release for maintenance and stability improvements
19
+ - Updated dependencies
20
+ - @objectstack/spec@0.7.1
21
+ - @objectstack/objectql@0.7.1
22
+ - @objectstack/runtime@0.7.1
23
+ - @objectstack/types@0.7.1
24
+
3
25
  ## 0.6.1
4
26
 
5
27
  ### Patch Changes
package/README.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  MSW (Mock Service Worker) Plugin for ObjectStack Runtime. This plugin enables seamless integration with [Mock Service Worker](https://mswjs.io/) for testing and development environments.
4
4
 
5
+ ## Plugin Capabilities
6
+
7
+ This plugin implements the ObjectStack plugin capability protocol:
8
+ - **Protocol**: `com.objectstack.protocol.testing.mock.v1` (full conformance)
9
+ - **Protocol**: `com.objectstack.protocol.api.rest.v1` (full conformance)
10
+ - **Provides**: `ObjectStackServer` interface for mock API operations
11
+ - **Requires**: `com.objectstack.engine.objectql` for data operations
12
+
13
+ See [objectstack.config.ts](./objectstack.config.ts) for the complete capability manifest.
14
+
5
15
  ## Features
6
16
 
7
17
  - 🎯 **Automatic API Mocking**: Automatically generates MSW handlers for all ObjectStack API endpoints
@@ -1,5 +1,5 @@
1
1
  import { Plugin, PluginContext } from '@objectstack/runtime';
2
- import { IObjectStackProtocol } from '@objectstack/spec/api';
2
+ import { ObjectStackProtocol } from '@objectstack/spec/api';
3
3
  export interface MSWPluginOptions {
4
4
  /**
5
5
  * Enable MSW in the browser environment
@@ -24,34 +24,93 @@ export interface MSWPluginOptions {
24
24
  export declare class ObjectStackServer {
25
25
  private static protocol;
26
26
  private static logger;
27
- static init(protocol: IObjectStackProtocol, logger?: (message: string, ...meta: any[]) => void): void;
27
+ static init(protocol: ObjectStackProtocol, logger?: any): void;
28
28
  static findData(object: string, params?: any): Promise<{
29
29
  status: number;
30
- data: any;
30
+ data: {
31
+ object: string;
32
+ records: Record<string, any>[];
33
+ total?: number | undefined;
34
+ hasMore?: boolean | undefined;
35
+ };
31
36
  }>;
32
37
  static getData(object: string, id: string): Promise<{
33
38
  status: number;
34
- data: any;
39
+ data: {
40
+ object: string;
41
+ record: Record<string, any>;
42
+ id: string;
43
+ };
44
+ } | {
45
+ status: number;
46
+ data: {
47
+ error: string;
48
+ };
35
49
  }>;
36
50
  static createData(object: string, data: any): Promise<{
37
51
  status: number;
38
- data: any;
52
+ data: {
53
+ object: string;
54
+ record: Record<string, any>;
55
+ id: string;
56
+ };
57
+ } | {
58
+ status: number;
59
+ data: {
60
+ error: string;
61
+ };
39
62
  }>;
40
63
  static updateData(object: string, id: string, data: any): Promise<{
41
64
  status: number;
42
- data: any;
65
+ data: {
66
+ object: string;
67
+ record: Record<string, any>;
68
+ id: string;
69
+ };
70
+ } | {
71
+ status: number;
72
+ data: {
73
+ error: string;
74
+ };
43
75
  }>;
44
76
  static deleteData(object: string, id: string): Promise<{
45
77
  status: number;
46
- data: any;
78
+ data: {
79
+ object: string;
80
+ id: string;
81
+ success: boolean;
82
+ };
83
+ } | {
84
+ status: number;
85
+ data: {
86
+ error: string;
87
+ };
47
88
  }>;
48
89
  static getUser(id: string): Promise<{
49
90
  status: number;
50
- data: any;
91
+ data: {
92
+ object: string;
93
+ record: Record<string, any>;
94
+ id: string;
95
+ };
96
+ } | {
97
+ status: number;
98
+ data: {
99
+ error: string;
100
+ };
51
101
  }>;
52
102
  static createUser(data: any): Promise<{
53
103
  status: number;
54
- data: any;
104
+ data: {
105
+ object: string;
106
+ record: Record<string, any>;
107
+ id: string;
108
+ };
109
+ } | {
110
+ status: number;
111
+ data: {
112
+ error: string;
113
+ };
55
114
  }>;
56
115
  }
57
116
  /**
@@ -1,4 +1,4 @@
1
- import { http, HttpResponse } from 'msw';
1
+ import { http, HttpResponse, passthrough } from 'msw';
2
2
  import { setupWorker } from 'msw/browser';
3
3
  import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
4
4
  /**
@@ -7,14 +7,20 @@ import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
7
7
  export class ObjectStackServer {
8
8
  static init(protocol, logger) {
9
9
  this.protocol = protocol;
10
- this.logger = logger || console.log;
10
+ this.logger = logger || {
11
+ info: console.log,
12
+ debug: console.debug,
13
+ warn: console.warn,
14
+ error: console.error
15
+ };
11
16
  }
12
17
  static async findData(object, params) {
13
18
  if (!this.protocol) {
14
19
  throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
15
20
  }
16
- this.logger?.(`[MSW] Finding ${object} records`, params);
17
- const result = await this.protocol.findData(object, params || {});
21
+ this.logger?.debug?.('MSW: Finding records', { object, params });
22
+ const result = await this.protocol.findData({ object, query: params || {} });
23
+ this.logger?.debug?.('MSW: Find completed', { object, count: result?.records?.length ?? 0 });
18
24
  return {
19
25
  status: 200,
20
26
  data: result
@@ -24,15 +30,17 @@ export class ObjectStackServer {
24
30
  if (!this.protocol) {
25
31
  throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
26
32
  }
27
- this.logger?.(`[MSW] Getting ${object} record:`, id);
33
+ this.logger?.debug?.('MSW: Getting record', { object, id });
28
34
  try {
29
- const result = await this.protocol.getData(object, id);
35
+ const result = await this.protocol.getData({ object, id });
36
+ this.logger?.debug?.('MSW: Get completed', { object, id });
30
37
  return {
31
38
  status: 200,
32
39
  data: result
33
40
  };
34
41
  }
35
42
  catch (error) {
43
+ this.logger?.warn?.('MSW: Get failed - not found', { object, id });
36
44
  const message = error instanceof Error ? error.message : 'Unknown error';
37
45
  return {
38
46
  status: 404,
@@ -44,15 +52,17 @@ export class ObjectStackServer {
44
52
  if (!this.protocol) {
45
53
  throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
46
54
  }
47
- this.logger?.(`[MSW] Creating ${object} record:`, data);
55
+ this.logger?.debug?.('MSW: Creating record', { object });
48
56
  try {
49
- const result = await this.protocol.createData(object, data);
57
+ const result = await this.protocol.createData({ object, data });
58
+ this.logger?.info?.('MSW: Record created', { object, id: result?.id });
50
59
  return {
51
60
  status: 201,
52
61
  data: result
53
62
  };
54
63
  }
55
64
  catch (error) {
65
+ this.logger?.error?.('MSW: Create failed', error, { object });
56
66
  const message = error instanceof Error ? error.message : 'Unknown error';
57
67
  return {
58
68
  status: 400,
@@ -64,15 +74,17 @@ export class ObjectStackServer {
64
74
  if (!this.protocol) {
65
75
  throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
66
76
  }
67
- this.logger?.(`[MSW] Updating ${object} record ${id}:`, data);
77
+ this.logger?.debug?.('MSW: Updating record', { object, id });
68
78
  try {
69
- const result = await this.protocol.updateData(object, id, data);
79
+ const result = await this.protocol.updateData({ object, id, data });
80
+ this.logger?.info?.('MSW: Record updated', { object, id });
70
81
  return {
71
82
  status: 200,
72
83
  data: result
73
84
  };
74
85
  }
75
86
  catch (error) {
87
+ this.logger?.error?.('MSW: Update failed', error, { object, id });
76
88
  const message = error instanceof Error ? error.message : 'Unknown error';
77
89
  return {
78
90
  status: 400,
@@ -84,15 +96,17 @@ export class ObjectStackServer {
84
96
  if (!this.protocol) {
85
97
  throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
86
98
  }
87
- this.logger?.(`[MSW] Deleting ${object} record:`, id);
99
+ this.logger?.debug?.('MSW: Deleting record', { object, id });
88
100
  try {
89
- const result = await this.protocol.deleteData(object, id);
101
+ const result = await this.protocol.deleteData({ object, id });
102
+ this.logger?.info?.('MSW: Record deleted', { object, id, success: result?.success });
90
103
  return {
91
104
  status: 200,
92
105
  data: result
93
106
  };
94
107
  }
95
108
  catch (error) {
109
+ this.logger?.error?.('MSW: Delete failed', error, { object, id });
96
110
  const message = error instanceof Error ? error.message : 'Unknown error';
97
111
  return {
98
112
  status: 400,
@@ -144,23 +158,30 @@ export class MSWPlugin {
144
158
  * Init phase
145
159
  */
146
160
  async init(ctx) {
161
+ ctx.logger.debug('Initializing MSW plugin', {
162
+ enableBrowser: this.options.enableBrowser,
163
+ baseUrl: this.options.baseUrl,
164
+ logRequests: this.options.logRequests
165
+ });
147
166
  // Protocol will be created in start phase
148
- ctx.logger.log('[MSWPlugin] Initialized');
167
+ ctx.logger.info('MSW plugin initialized');
149
168
  }
150
169
  /**
151
170
  * Start phase
152
171
  */
153
172
  async start(ctx) {
173
+ ctx.logger.debug('Starting MSW plugin');
154
174
  try {
155
175
  const dataEngine = ctx.getService('objectql');
156
176
  this.protocol = new ObjectStackProtocolImplementation(dataEngine);
177
+ ctx.logger.debug('Protocol implementation created');
157
178
  }
158
179
  catch (e) {
159
- console.error('[MSWPlugin] Failed to initialize protocol', e);
180
+ ctx.logger.error('Failed to initialize protocol', e);
160
181
  throw new Error('[MSWPlugin] Failed to initialize protocol (missing objectql service?)');
161
182
  }
162
- this.setupHandlers();
163
- await this.startWorker();
183
+ this.setupHandlers(ctx);
184
+ await this.startWorker(ctx);
164
185
  }
165
186
  /**
166
187
  * Destroy phase
@@ -171,30 +192,43 @@ export class MSWPlugin {
171
192
  /**
172
193
  * Setup MSW handlers
173
194
  */
174
- setupHandlers() {
195
+ setupHandlers(ctx) {
175
196
  if (!this.protocol) {
176
197
  throw new Error('[MSWPlugin] Protocol not initialized');
177
198
  }
178
199
  const protocol = this.protocol;
179
- // Initialize ObjectStackServer
180
- ObjectStackServer.init(protocol, this.options.logRequests ? console.log : undefined);
200
+ // Initialize ObjectStackServer with structured logger
201
+ ObjectStackServer.init(protocol, this.options.logRequests ? ctx.logger : undefined);
202
+ ctx.logger.debug('Initialized ObjectStackServer', { logRequests: this.options.logRequests });
181
203
  const baseUrl = this.options.baseUrl || '/api/v1';
182
204
  // Define standard ObjectStack API handlers
183
205
  this.handlers = [
206
+ // Passthrough for external resources
207
+ http.get('https://fonts.googleapis.com/*', () => passthrough()),
208
+ http.get('https://fonts.gstatic.com/*', () => passthrough()),
184
209
  // Discovery endpoint
185
- http.get(`${baseUrl}`, () => {
186
- return HttpResponse.json(protocol.getDiscovery());
210
+ http.get(`${baseUrl}`, async () => {
211
+ const discovery = await protocol.getDiscovery({});
212
+ return HttpResponse.json({
213
+ ...discovery,
214
+ routes: {
215
+ data: `${baseUrl}/data`,
216
+ metadata: `${baseUrl}/meta`,
217
+ ui: `${baseUrl}/ui`,
218
+ auth: `${baseUrl}/auth`
219
+ }
220
+ });
187
221
  }),
188
222
  // Meta endpoints
189
- http.get(`${baseUrl}/meta`, () => {
190
- return HttpResponse.json(protocol.getMetaTypes());
223
+ http.get(`${baseUrl}/meta`, async () => {
224
+ return HttpResponse.json(await protocol.getMetaTypes({}));
191
225
  }),
192
- http.get(`${baseUrl}/meta/:type`, ({ params }) => {
193
- return HttpResponse.json(protocol.getMetaItems(params.type));
226
+ http.get(`${baseUrl}/meta/:type`, async ({ params }) => {
227
+ return HttpResponse.json(await protocol.getMetaItems({ type: params.type }));
194
228
  }),
195
- http.get(`${baseUrl}/meta/:type/:name`, ({ params }) => {
229
+ http.get(`${baseUrl}/meta/:type/:name`, async ({ params }) => {
196
230
  try {
197
- return HttpResponse.json(protocol.getMetaItem(params.type, params.name));
231
+ return HttpResponse.json(await protocol.getMetaItem({ type: params.type, name: params.name }));
198
232
  }
199
233
  catch (error) {
200
234
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -210,7 +244,10 @@ export class MSWPlugin {
210
244
  queryParams[key] = value;
211
245
  });
212
246
  const result = await ObjectStackServer.findData(params.object, queryParams);
213
- return HttpResponse.json(result.data, { status: result.status });
247
+ return HttpResponse.json(result.data, {
248
+ status: result.status,
249
+ headers: { 'Cache-Control': 'no-store' }
250
+ });
214
251
  }
215
252
  catch (error) {
216
253
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -220,7 +257,10 @@ export class MSWPlugin {
220
257
  http.get(`${baseUrl}/data/:object/:id`, async ({ params }) => {
221
258
  try {
222
259
  const result = await ObjectStackServer.getData(params.object, params.id);
223
- return HttpResponse.json(result.data, { status: result.status });
260
+ return HttpResponse.json(result.data, {
261
+ status: result.status,
262
+ headers: { 'Cache-Control': 'no-store' }
263
+ });
224
264
  }
225
265
  catch (error) {
226
266
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -259,12 +299,102 @@ export class MSWPlugin {
259
299
  return HttpResponse.json({ error: message }, { status: 400 });
260
300
  }
261
301
  }),
302
+ // Batch Operations
303
+ http.post(`${baseUrl}/data/:object/batch`, async ({ params, request }) => {
304
+ try {
305
+ const body = await request.json();
306
+ const result = await protocol.batchData({ object: params.object, request: body });
307
+ return HttpResponse.json(result);
308
+ }
309
+ catch (error) {
310
+ const message = error instanceof Error ? error.message : 'Unknown error';
311
+ return HttpResponse.json({ error: message }, { status: 400 });
312
+ }
313
+ }),
314
+ http.post(`${baseUrl}/data/:object/createMany`, async ({ params, request }) => {
315
+ try {
316
+ const body = await request.json();
317
+ const records = Array.isArray(body) ? body : [];
318
+ const result = await protocol.createManyData({ object: params.object, records });
319
+ return HttpResponse.json(result, { status: 201 });
320
+ }
321
+ catch (error) {
322
+ const message = error instanceof Error ? error.message : 'Unknown error';
323
+ return HttpResponse.json({ error: message }, { status: 400 });
324
+ }
325
+ }),
326
+ http.post(`${baseUrl}/data/:object/updateMany`, async ({ params, request }) => {
327
+ try {
328
+ const body = await request.json();
329
+ const result = await protocol.updateManyData({
330
+ object: params.object,
331
+ records: body?.records || [],
332
+ options: body?.options
333
+ });
334
+ return HttpResponse.json(result);
335
+ }
336
+ catch (error) {
337
+ const message = error instanceof Error ? error.message : 'Unknown error';
338
+ return HttpResponse.json({ error: message }, { status: 400 });
339
+ }
340
+ }),
341
+ http.post(`${baseUrl}/data/:object/deleteMany`, async ({ params, request }) => {
342
+ try {
343
+ const body = await request.json();
344
+ const result = await protocol.deleteManyData({
345
+ object: params.object,
346
+ ids: body?.ids || [],
347
+ options: body?.options
348
+ });
349
+ return HttpResponse.json(result);
350
+ }
351
+ catch (error) {
352
+ const message = error instanceof Error ? error.message : 'Unknown error';
353
+ return HttpResponse.json({ error: message }, { status: 400 });
354
+ }
355
+ }),
356
+ // Enhanced Metadata with Cache Support
357
+ http.get(`${baseUrl}/meta/:type/:name`, async ({ params, request }) => {
358
+ try {
359
+ const cacheRequest = {
360
+ ifNoneMatch: request.headers.get('if-none-match') || undefined,
361
+ ifModifiedSince: request.headers.get('if-modified-since') || undefined,
362
+ };
363
+ const result = await protocol.getMetaItemCached({
364
+ type: params.type,
365
+ name: params.name,
366
+ cacheRequest
367
+ });
368
+ if (result.notModified) {
369
+ return new HttpResponse(null, { status: 304 });
370
+ }
371
+ // Build response headers
372
+ const headers = {};
373
+ if (result.etag) {
374
+ const etagValue = result.etag.weak ? `W/"${result.etag.value}"` : `"${result.etag.value}"`;
375
+ headers['ETag'] = etagValue;
376
+ }
377
+ if (result.lastModified) {
378
+ headers['Last-Modified'] = new Date(result.lastModified).toUTCString();
379
+ }
380
+ if (result.cacheControl) {
381
+ const directives = result.cacheControl.directives.join(', ');
382
+ const maxAge = result.cacheControl.maxAge ? `, max-age=${result.cacheControl.maxAge}` : '';
383
+ headers['Cache-Control'] = directives + maxAge;
384
+ }
385
+ return HttpResponse.json(result.data, { headers });
386
+ }
387
+ catch (error) {
388
+ const message = error instanceof Error ? error.message : 'Unknown error';
389
+ return HttpResponse.json({ error: message }, { status: 404 });
390
+ }
391
+ }),
262
392
  // UI Protocol endpoint
263
- http.get(`${baseUrl}/ui/view/:object`, ({ params, request }) => {
393
+ http.get(`${baseUrl}/ui/view/:object`, async ({ params, request }) => {
264
394
  try {
265
395
  const url = new URL(request.url);
266
396
  const viewType = url.searchParams.get('type') || 'list';
267
- const view = protocol.getUiView(params.object, viewType);
397
+ const view = await protocol.getUiView({ object: params.object, type: viewType });
268
398
  return HttpResponse.json(view);
269
399
  }
270
400
  catch (error) {
@@ -272,25 +402,129 @@ export class MSWPlugin {
272
402
  return HttpResponse.json({ error: message }, { status: 404 });
273
403
  }
274
404
  }),
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
+ }),
275
508
  // Add custom handlers
276
509
  ...(this.options.customHandlers || [])
277
510
  ];
278
- console.log(`[MSWPlugin] Installed ${this.handlers.length} request handlers.`);
511
+ ctx.logger.info('MSW request handlers installed', { count: this.handlers.length, baseUrl });
279
512
  }
280
513
  /**
281
514
  * Start the MSW worker
282
515
  */
283
- async startWorker() {
516
+ async startWorker(ctx) {
284
517
  if (this.options.enableBrowser && typeof window !== 'undefined') {
285
518
  // Browser environment
519
+ ctx.logger.debug('Starting MSW in browser mode');
286
520
  this.worker = setupWorker(...this.handlers);
287
521
  await this.worker.start({
288
522
  onUnhandledRequest: 'bypass',
289
523
  });
290
- console.log(`[MSWPlugin] Started MSW in browser mode.`);
524
+ ctx.logger.info('MSW started in browser mode');
291
525
  }
292
526
  else {
293
- console.log(`[MSWPlugin] Browser mode disabled or not in browser environment.`);
527
+ ctx.logger.debug('MSW browser mode disabled or not in browser environment');
294
528
  }
295
529
  }
296
530
  /**
@@ -299,7 +533,7 @@ export class MSWPlugin {
299
533
  async stopWorker() {
300
534
  if (this.worker) {
301
535
  this.worker.stop();
302
- console.log(`[MSWPlugin] Stopped MSW worker.`);
536
+ console.log('[MSWPlugin] Stopped MSW worker');
303
537
  }
304
538
  }
305
539
  /**