@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 +22 -0
- package/README.md +10 -0
- package/dist/msw-plugin.d.ts +68 -9
- package/dist/msw-plugin.js +270 -36
- package/objectstack.config.ts +273 -0
- package/package.json +6 -6
- package/src/msw-plugin.ts +274 -41
package/src/msw-plugin.ts
CHANGED
|
@@ -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 {
|
|
4
4
|
Plugin,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
IDataEngine
|
|
8
8
|
} from '@objectstack/runtime';
|
|
9
9
|
import { ObjectStackProtocolImplementation } from '@objectstack/objectql';
|
|
10
|
-
import {
|
|
10
|
+
import { ObjectStackProtocol } from '@objectstack/spec/api';
|
|
11
11
|
// import { IDataEngine } from '@objectstack/core';
|
|
12
12
|
|
|
13
13
|
export interface MSWPluginOptions {
|
|
@@ -36,12 +36,17 @@ export interface MSWPluginOptions {
|
|
|
36
36
|
* ObjectStack Server Mock - Provides mock database functionality
|
|
37
37
|
*/
|
|
38
38
|
export class ObjectStackServer {
|
|
39
|
-
private static protocol:
|
|
40
|
-
private static logger:
|
|
39
|
+
private static protocol: ObjectStackProtocol | null = null;
|
|
40
|
+
private static logger: any | null = null;
|
|
41
41
|
|
|
42
|
-
static init(protocol:
|
|
42
|
+
static init(protocol: ObjectStackProtocol, logger?: any) {
|
|
43
43
|
this.protocol = protocol;
|
|
44
|
-
this.logger = logger ||
|
|
44
|
+
this.logger = logger || {
|
|
45
|
+
info: console.log,
|
|
46
|
+
debug: console.debug,
|
|
47
|
+
warn: console.warn,
|
|
48
|
+
error: console.error
|
|
49
|
+
};
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
static async findData(object: string, params?: any) {
|
|
@@ -49,8 +54,9 @@ export class ObjectStackServer {
|
|
|
49
54
|
throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
this.logger?.(
|
|
53
|
-
const result = await this.protocol.findData(object, params || {});
|
|
57
|
+
this.logger?.debug?.('MSW: Finding records', { object, params });
|
|
58
|
+
const result = await this.protocol.findData({ object, query: params || {} });
|
|
59
|
+
this.logger?.debug?.('MSW: Find completed', { object, count: result?.records?.length ?? 0 });
|
|
54
60
|
return {
|
|
55
61
|
status: 200,
|
|
56
62
|
data: result
|
|
@@ -62,14 +68,16 @@ export class ObjectStackServer {
|
|
|
62
68
|
throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
this.logger?.(
|
|
71
|
+
this.logger?.debug?.('MSW: Getting record', { object, id });
|
|
66
72
|
try {
|
|
67
|
-
const result = await this.protocol.getData(object, id);
|
|
73
|
+
const result = await this.protocol.getData({ object, id });
|
|
74
|
+
this.logger?.debug?.('MSW: Get completed', { object, id });
|
|
68
75
|
return {
|
|
69
76
|
status: 200,
|
|
70
77
|
data: result
|
|
71
78
|
};
|
|
72
79
|
} catch (error) {
|
|
80
|
+
this.logger?.warn?.('MSW: Get failed - not found', { object, id });
|
|
73
81
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
74
82
|
return {
|
|
75
83
|
status: 404,
|
|
@@ -83,14 +91,16 @@ export class ObjectStackServer {
|
|
|
83
91
|
throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
this.logger?.(
|
|
94
|
+
this.logger?.debug?.('MSW: Creating record', { object });
|
|
87
95
|
try {
|
|
88
|
-
const result = await this.protocol.createData(object, data);
|
|
96
|
+
const result = await this.protocol.createData({ object, data });
|
|
97
|
+
this.logger?.info?.('MSW: Record created', { object, id: result?.id });
|
|
89
98
|
return {
|
|
90
99
|
status: 201,
|
|
91
100
|
data: result
|
|
92
101
|
};
|
|
93
102
|
} catch (error) {
|
|
103
|
+
this.logger?.error?.('MSW: Create failed', error, { object });
|
|
94
104
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
95
105
|
return {
|
|
96
106
|
status: 400,
|
|
@@ -104,14 +114,16 @@ export class ObjectStackServer {
|
|
|
104
114
|
throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
|
|
105
115
|
}
|
|
106
116
|
|
|
107
|
-
this.logger?.(
|
|
117
|
+
this.logger?.debug?.('MSW: Updating record', { object, id });
|
|
108
118
|
try {
|
|
109
|
-
const result = await this.protocol.updateData(object, id, data);
|
|
119
|
+
const result = await this.protocol.updateData({ object, id, data });
|
|
120
|
+
this.logger?.info?.('MSW: Record updated', { object, id });
|
|
110
121
|
return {
|
|
111
122
|
status: 200,
|
|
112
123
|
data: result
|
|
113
124
|
};
|
|
114
125
|
} catch (error) {
|
|
126
|
+
this.logger?.error?.('MSW: Update failed', error, { object, id });
|
|
115
127
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
116
128
|
return {
|
|
117
129
|
status: 400,
|
|
@@ -125,14 +137,16 @@ export class ObjectStackServer {
|
|
|
125
137
|
throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
|
|
126
138
|
}
|
|
127
139
|
|
|
128
|
-
this.logger?.(
|
|
140
|
+
this.logger?.debug?.('MSW: Deleting record', { object, id });
|
|
129
141
|
try {
|
|
130
|
-
const result = await this.protocol.deleteData(object, id);
|
|
142
|
+
const result = await this.protocol.deleteData({ object, id });
|
|
143
|
+
this.logger?.info?.('MSW: Record deleted', { object, id, success: result?.success });
|
|
131
144
|
return {
|
|
132
145
|
status: 200,
|
|
133
146
|
data: result
|
|
134
147
|
};
|
|
135
148
|
} catch (error) {
|
|
149
|
+
this.logger?.error?.('MSW: Delete failed', error, { object, id });
|
|
136
150
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
137
151
|
return {
|
|
138
152
|
status: 400,
|
|
@@ -176,7 +190,7 @@ export class MSWPlugin implements Plugin {
|
|
|
176
190
|
private options: MSWPluginOptions;
|
|
177
191
|
private worker: any;
|
|
178
192
|
private handlers: Array<any> = [];
|
|
179
|
-
private protocol?:
|
|
193
|
+
private protocol?: ObjectStackProtocol;
|
|
180
194
|
|
|
181
195
|
constructor(options: MSWPluginOptions = {}) {
|
|
182
196
|
this.options = {
|
|
@@ -191,24 +205,32 @@ export class MSWPlugin implements Plugin {
|
|
|
191
205
|
* Init phase
|
|
192
206
|
*/
|
|
193
207
|
async init(ctx: PluginContext) {
|
|
208
|
+
ctx.logger.debug('Initializing MSW plugin', {
|
|
209
|
+
enableBrowser: this.options.enableBrowser,
|
|
210
|
+
baseUrl: this.options.baseUrl,
|
|
211
|
+
logRequests: this.options.logRequests
|
|
212
|
+
});
|
|
194
213
|
// Protocol will be created in start phase
|
|
195
|
-
ctx.logger.
|
|
214
|
+
ctx.logger.info('MSW plugin initialized');
|
|
196
215
|
}
|
|
197
216
|
|
|
198
217
|
/**
|
|
199
218
|
* Start phase
|
|
200
219
|
*/
|
|
201
220
|
async start(ctx: PluginContext) {
|
|
221
|
+
ctx.logger.debug('Starting MSW plugin');
|
|
222
|
+
|
|
202
223
|
try {
|
|
203
224
|
const dataEngine = ctx.getService<IDataEngine>('objectql');
|
|
204
225
|
this.protocol = new ObjectStackProtocolImplementation(dataEngine);
|
|
226
|
+
ctx.logger.debug('Protocol implementation created');
|
|
205
227
|
} catch (e) {
|
|
206
|
-
|
|
228
|
+
ctx.logger.error('Failed to initialize protocol', e as Error);
|
|
207
229
|
throw new Error('[MSWPlugin] Failed to initialize protocol (missing objectql service?)');
|
|
208
230
|
}
|
|
209
231
|
|
|
210
|
-
this.setupHandlers();
|
|
211
|
-
await this.startWorker();
|
|
232
|
+
this.setupHandlers(ctx);
|
|
233
|
+
await this.startWorker(ctx);
|
|
212
234
|
}
|
|
213
235
|
|
|
214
236
|
/**
|
|
@@ -221,41 +243,56 @@ export class MSWPlugin implements Plugin {
|
|
|
221
243
|
/**
|
|
222
244
|
* Setup MSW handlers
|
|
223
245
|
*/
|
|
224
|
-
private setupHandlers() {
|
|
246
|
+
private setupHandlers(ctx: PluginContext) {
|
|
225
247
|
if (!this.protocol) {
|
|
226
248
|
throw new Error('[MSWPlugin] Protocol not initialized');
|
|
227
249
|
}
|
|
228
250
|
|
|
229
251
|
const protocol = this.protocol;
|
|
230
252
|
|
|
231
|
-
// Initialize ObjectStackServer
|
|
253
|
+
// Initialize ObjectStackServer with structured logger
|
|
232
254
|
ObjectStackServer.init(
|
|
233
255
|
protocol,
|
|
234
|
-
this.options.logRequests ?
|
|
256
|
+
this.options.logRequests ? ctx.logger : undefined
|
|
235
257
|
);
|
|
236
258
|
|
|
259
|
+
ctx.logger.debug('Initialized ObjectStackServer', { logRequests: this.options.logRequests });
|
|
260
|
+
|
|
237
261
|
const baseUrl = this.options.baseUrl || '/api/v1';
|
|
238
262
|
|
|
239
263
|
// Define standard ObjectStack API handlers
|
|
240
264
|
this.handlers = [
|
|
265
|
+
// Passthrough for external resources
|
|
266
|
+
http.get('https://fonts.googleapis.com/*', () => passthrough()),
|
|
267
|
+
http.get('https://fonts.gstatic.com/*', () => passthrough()),
|
|
268
|
+
|
|
241
269
|
// Discovery endpoint
|
|
242
|
-
http.get(`${baseUrl}`, () => {
|
|
243
|
-
|
|
270
|
+
http.get(`${baseUrl}`, async () => {
|
|
271
|
+
const discovery = await protocol.getDiscovery({});
|
|
272
|
+
return HttpResponse.json({
|
|
273
|
+
...discovery,
|
|
274
|
+
routes: {
|
|
275
|
+
data: `${baseUrl}/data`,
|
|
276
|
+
metadata: `${baseUrl}/meta`,
|
|
277
|
+
ui: `${baseUrl}/ui`,
|
|
278
|
+
auth: `${baseUrl}/auth`
|
|
279
|
+
}
|
|
280
|
+
});
|
|
244
281
|
}),
|
|
245
282
|
|
|
246
283
|
// Meta endpoints
|
|
247
|
-
http.get(`${baseUrl}/meta`, () => {
|
|
248
|
-
return HttpResponse.json(protocol.getMetaTypes());
|
|
284
|
+
http.get(`${baseUrl}/meta`, async () => {
|
|
285
|
+
return HttpResponse.json(await protocol.getMetaTypes({}));
|
|
249
286
|
}),
|
|
250
287
|
|
|
251
|
-
http.get(`${baseUrl}/meta/:type`, ({ params }) => {
|
|
252
|
-
return HttpResponse.json(protocol.getMetaItems(params.type as string));
|
|
288
|
+
http.get(`${baseUrl}/meta/:type`, async ({ params }) => {
|
|
289
|
+
return HttpResponse.json(await protocol.getMetaItems({ type: params.type as string }));
|
|
253
290
|
}),
|
|
254
291
|
|
|
255
|
-
http.get(`${baseUrl}/meta/:type/:name`, ({ params }) => {
|
|
292
|
+
http.get(`${baseUrl}/meta/:type/:name`, async ({ params }) => {
|
|
256
293
|
try {
|
|
257
294
|
return HttpResponse.json(
|
|
258
|
-
protocol.getMetaItem(params.type as string, params.name as string)
|
|
295
|
+
await protocol.getMetaItem({ type: params.type as string, name: params.name as string })
|
|
259
296
|
);
|
|
260
297
|
} catch (error) {
|
|
261
298
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -276,7 +313,10 @@ export class MSWPlugin implements Plugin {
|
|
|
276
313
|
params.object as string,
|
|
277
314
|
queryParams
|
|
278
315
|
);
|
|
279
|
-
return HttpResponse.json(result.data, {
|
|
316
|
+
return HttpResponse.json(result.data, {
|
|
317
|
+
status: result.status,
|
|
318
|
+
headers: { 'Cache-Control': 'no-store' }
|
|
319
|
+
});
|
|
280
320
|
} catch (error) {
|
|
281
321
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
282
322
|
return HttpResponse.json({ error: message }, { status: 404 });
|
|
@@ -289,7 +329,10 @@ export class MSWPlugin implements Plugin {
|
|
|
289
329
|
params.object as string,
|
|
290
330
|
params.id as string
|
|
291
331
|
);
|
|
292
|
-
return HttpResponse.json(result.data, {
|
|
332
|
+
return HttpResponse.json(result.data, {
|
|
333
|
+
status: result.status,
|
|
334
|
+
headers: { 'Cache-Control': 'no-store' }
|
|
335
|
+
});
|
|
293
336
|
} catch (error) {
|
|
294
337
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
295
338
|
return HttpResponse.json({ error: message }, { status: 404 });
|
|
@@ -338,12 +381,106 @@ export class MSWPlugin implements Plugin {
|
|
|
338
381
|
}
|
|
339
382
|
}),
|
|
340
383
|
|
|
384
|
+
// Batch Operations
|
|
385
|
+
http.post(`${baseUrl}/data/:object/batch`, async ({ params, request }) => {
|
|
386
|
+
try {
|
|
387
|
+
const body = await request.json();
|
|
388
|
+
const result = await protocol.batchData({ object: params.object as string, request: body as any });
|
|
389
|
+
return HttpResponse.json(result);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
392
|
+
return HttpResponse.json({ error: message }, { status: 400 });
|
|
393
|
+
}
|
|
394
|
+
}),
|
|
395
|
+
|
|
396
|
+
http.post(`${baseUrl}/data/:object/createMany`, async ({ params, request }) => {
|
|
397
|
+
try {
|
|
398
|
+
const body = await request.json();
|
|
399
|
+
const records = Array.isArray(body) ? body : [];
|
|
400
|
+
const result = await protocol.createManyData({ object: params.object as string, records });
|
|
401
|
+
return HttpResponse.json(result, { status: 201 });
|
|
402
|
+
} catch (error) {
|
|
403
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
404
|
+
return HttpResponse.json({ error: message }, { status: 400 });
|
|
405
|
+
}
|
|
406
|
+
}),
|
|
407
|
+
|
|
408
|
+
http.post(`${baseUrl}/data/:object/updateMany`, async ({ params, request }) => {
|
|
409
|
+
try {
|
|
410
|
+
const body = await request.json() as any;
|
|
411
|
+
const result = await protocol.updateManyData({
|
|
412
|
+
object: params.object as string,
|
|
413
|
+
records: body?.records || [],
|
|
414
|
+
options: body?.options
|
|
415
|
+
});
|
|
416
|
+
return HttpResponse.json(result);
|
|
417
|
+
} catch (error) {
|
|
418
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
419
|
+
return HttpResponse.json({ error: message }, { status: 400 });
|
|
420
|
+
}
|
|
421
|
+
}),
|
|
422
|
+
|
|
423
|
+
http.post(`${baseUrl}/data/:object/deleteMany`, async ({ params, request }) => {
|
|
424
|
+
try {
|
|
425
|
+
const body = await request.json() as any;
|
|
426
|
+
const result = await protocol.deleteManyData({
|
|
427
|
+
object: params.object as string,
|
|
428
|
+
ids: body?.ids || [],
|
|
429
|
+
options: body?.options
|
|
430
|
+
});
|
|
431
|
+
return HttpResponse.json(result);
|
|
432
|
+
} catch (error) {
|
|
433
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
434
|
+
return HttpResponse.json({ error: message }, { status: 400 });
|
|
435
|
+
}
|
|
436
|
+
}),
|
|
437
|
+
|
|
438
|
+
// Enhanced Metadata with Cache Support
|
|
439
|
+
http.get(`${baseUrl}/meta/:type/:name`, async ({ params, request }) => {
|
|
440
|
+
try {
|
|
441
|
+
const cacheRequest = {
|
|
442
|
+
ifNoneMatch: request.headers.get('if-none-match') || undefined,
|
|
443
|
+
ifModifiedSince: request.headers.get('if-modified-since') || undefined,
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const result = await protocol.getMetaItemCached({
|
|
447
|
+
type: params.type as string,
|
|
448
|
+
name: params.name as string,
|
|
449
|
+
cacheRequest
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
if (result.notModified) {
|
|
453
|
+
return new HttpResponse(null, { status: 304 });
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Build response headers
|
|
457
|
+
const headers: Record<string, string> = {};
|
|
458
|
+
if (result.etag) {
|
|
459
|
+
const etagValue = result.etag.weak ? `W/"${result.etag.value}"` : `"${result.etag.value}"`;
|
|
460
|
+
headers['ETag'] = etagValue;
|
|
461
|
+
}
|
|
462
|
+
if (result.lastModified) {
|
|
463
|
+
headers['Last-Modified'] = new Date(result.lastModified).toUTCString();
|
|
464
|
+
}
|
|
465
|
+
if (result.cacheControl) {
|
|
466
|
+
const directives = result.cacheControl.directives.join(', ');
|
|
467
|
+
const maxAge = result.cacheControl.maxAge ? `, max-age=${result.cacheControl.maxAge}` : '';
|
|
468
|
+
headers['Cache-Control'] = directives + maxAge;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
return HttpResponse.json(result.data, { headers });
|
|
472
|
+
} catch (error) {
|
|
473
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
474
|
+
return HttpResponse.json({ error: message }, { status: 404 });
|
|
475
|
+
}
|
|
476
|
+
}),
|
|
477
|
+
|
|
341
478
|
// UI Protocol endpoint
|
|
342
|
-
http.get(`${baseUrl}/ui/view/:object`, ({ params, request }) => {
|
|
479
|
+
http.get(`${baseUrl}/ui/view/:object`, async ({ params, request }) => {
|
|
343
480
|
try {
|
|
344
481
|
const url = new URL(request.url);
|
|
345
482
|
const viewType = url.searchParams.get('type') || 'list';
|
|
346
|
-
const view = protocol.getUiView(params.object as string, viewType as 'list' | 'form');
|
|
483
|
+
const view = await protocol.getUiView({ object: params.object as string, type: viewType as 'list' | 'form' });
|
|
347
484
|
return HttpResponse.json(view);
|
|
348
485
|
} catch (error) {
|
|
349
486
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -351,26 +488,122 @@ export class MSWPlugin implements Plugin {
|
|
|
351
488
|
}
|
|
352
489
|
}),
|
|
353
490
|
|
|
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
|
+
|
|
354
586
|
// Add custom handlers
|
|
355
587
|
...(this.options.customHandlers || [])
|
|
356
588
|
];
|
|
357
589
|
|
|
358
|
-
|
|
590
|
+
ctx.logger.info('MSW request handlers installed', { count: this.handlers.length, baseUrl });
|
|
359
591
|
}
|
|
360
592
|
|
|
361
593
|
/**
|
|
362
594
|
* Start the MSW worker
|
|
363
595
|
*/
|
|
364
|
-
private async startWorker() {
|
|
596
|
+
private async startWorker(ctx: PluginContext) {
|
|
365
597
|
if (this.options.enableBrowser && typeof window !== 'undefined') {
|
|
366
598
|
// Browser environment
|
|
599
|
+
ctx.logger.debug('Starting MSW in browser mode');
|
|
367
600
|
this.worker = setupWorker(...this.handlers);
|
|
368
601
|
await this.worker.start({
|
|
369
602
|
onUnhandledRequest: 'bypass',
|
|
370
603
|
});
|
|
371
|
-
|
|
604
|
+
ctx.logger.info('MSW started in browser mode');
|
|
372
605
|
} else {
|
|
373
|
-
|
|
606
|
+
ctx.logger.debug('MSW browser mode disabled or not in browser environment');
|
|
374
607
|
}
|
|
375
608
|
}
|
|
376
609
|
|
|
@@ -380,7 +613,7 @@ export class MSWPlugin implements Plugin {
|
|
|
380
613
|
private async stopWorker() {
|
|
381
614
|
if (this.worker) {
|
|
382
615
|
this.worker.stop();
|
|
383
|
-
console.log(
|
|
616
|
+
console.log('[MSWPlugin] Stopped MSW worker');
|
|
384
617
|
}
|
|
385
618
|
}
|
|
386
619
|
|