@objectstack/plugin-msw 1.0.1 → 1.0.4

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.
@@ -1,6 +1,6 @@
1
1
  import { http, HttpResponse } from 'msw';
2
2
  import { setupWorker } from 'msw/browser';
3
- // import { IDataEngine } from '@objectstack/core';
3
+ import { HttpDispatcher } from '@objectstack/runtime';
4
4
  // Helper for parsing query parameters
5
5
  function parseQueryParams(url) {
6
6
  const params = {};
@@ -43,245 +43,9 @@ function parseQueryParams(url) {
43
43
  }
44
44
  return params;
45
45
  }
46
- // Helper to normalize flat parameters into 'where' clause
47
- function normalizeQuery(params) {
48
- // If 'where' is already present, trust it
49
- if (params.where)
50
- return params;
51
- const reserved = ['select', 'order', 'orderBy', 'sort', 'limit', 'skip', 'offset', 'top', 'page', 'pageSize', 'count'];
52
- const where = {};
53
- let hasWhere = false;
54
- for (const key in params) {
55
- if (!reserved.includes(key)) {
56
- where[key] = params[key];
57
- hasWhere = true;
58
- }
59
- }
60
- if (hasWhere) {
61
- // Keep original params but add where.
62
- // This allows protocols that look at root properties to still work,
63
- // while providing 'where' for strict drivers.
64
- return { ...params, where };
65
- }
66
- return params;
67
- }
68
- /**
69
- * ObjectStack Server Mock - Provides mock database functionality
70
- */
71
- export class ObjectStackServer {
72
- static init(protocol, logger) {
73
- this.protocol = protocol;
74
- this.logger = logger || {
75
- info: console.log,
76
- debug: console.debug,
77
- warn: console.warn,
78
- error: console.error
79
- };
80
- }
81
- static async findData(object, params) {
82
- if (!this.protocol) {
83
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
84
- }
85
- this.logger?.debug?.('MSW: Finding records', { object, params });
86
- const result = await this.protocol.findData({ object, query: params || {} });
87
- this.logger?.debug?.('MSW: Find completed', { object, count: result?.records?.length ?? 0 });
88
- return {
89
- status: 200,
90
- data: result
91
- };
92
- }
93
- static async getData(object, id) {
94
- if (!this.protocol) {
95
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
96
- }
97
- this.logger?.debug?.('MSW: Getting record', { object, id });
98
- try {
99
- const result = await this.protocol.getData({ object, id });
100
- this.logger?.debug?.('MSW: Get completed', { object, id });
101
- return {
102
- status: 200,
103
- data: result
104
- };
105
- }
106
- catch (error) {
107
- this.logger?.warn?.('MSW: Get failed - not found', { object, id });
108
- const message = error instanceof Error ? error.message : 'Unknown error';
109
- return {
110
- status: 404,
111
- data: { error: message }
112
- };
113
- }
114
- }
115
- static async createData(object, data) {
116
- if (!this.protocol) {
117
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
118
- }
119
- this.logger?.debug?.('MSW: Creating record', { object });
120
- try {
121
- const result = await this.protocol.createData({ object, data });
122
- this.logger?.info?.('MSW: Record created', { object, id: result?.id });
123
- return {
124
- status: 201,
125
- data: result
126
- };
127
- }
128
- catch (error) {
129
- this.logger?.error?.('MSW: Create failed', error, { object });
130
- const message = error instanceof Error ? error.message : 'Unknown error';
131
- return {
132
- status: 400,
133
- data: { error: message }
134
- };
135
- }
136
- }
137
- static async updateData(object, id, data) {
138
- if (!this.protocol) {
139
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
140
- }
141
- this.logger?.debug?.('MSW: Updating record', { object, id });
142
- try {
143
- const result = await this.protocol.updateData({ object, id, data });
144
- this.logger?.info?.('MSW: Record updated', { object, id });
145
- return {
146
- status: 200,
147
- data: result
148
- };
149
- }
150
- catch (error) {
151
- this.logger?.error?.('MSW: Update failed', error, { object, id });
152
- const message = error instanceof Error ? error.message : 'Unknown error';
153
- return {
154
- status: 400,
155
- data: { error: message }
156
- };
157
- }
158
- }
159
- static async deleteData(object, id) {
160
- if (!this.protocol) {
161
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
162
- }
163
- this.logger?.debug?.('MSW: Deleting record', { object, id });
164
- try {
165
- const result = await this.protocol.deleteData({ object, id });
166
- this.logger?.info?.('MSW: Record deleted', { object, id, success: result?.success });
167
- return {
168
- status: 200,
169
- data: result
170
- };
171
- }
172
- catch (error) {
173
- this.logger?.error?.('MSW: Delete failed', error, { object, id });
174
- const message = error instanceof Error ? error.message : 'Unknown error';
175
- return {
176
- status: 400,
177
- data: { error: message }
178
- };
179
- }
180
- }
181
- static async analyticsQuery(request) {
182
- if (!this.protocol) {
183
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
184
- }
185
- this.logger?.debug?.('MSW: Executing analytics query', { request });
186
- try {
187
- const result = await this.protocol.analyticsQuery(request);
188
- this.logger?.debug?.('MSW: Analytics query completed', { result });
189
- return {
190
- status: 200,
191
- data: result
192
- };
193
- }
194
- catch (error) {
195
- this.logger?.error?.('MSW: Analytics query failed', error);
196
- const message = error instanceof Error ? error.message : 'Unknown error';
197
- return {
198
- status: 400,
199
- data: { error: message }
200
- };
201
- }
202
- }
203
- static async getAnalyticsMeta(request) {
204
- if (!this.protocol) {
205
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
206
- }
207
- this.logger?.debug?.('MSW: Getting analytics metadata', { request });
208
- try {
209
- const result = await this.protocol.getAnalyticsMeta(request);
210
- this.logger?.debug?.('MSW: Analytics metadata retrieved', { result });
211
- return {
212
- status: 200,
213
- data: result
214
- };
215
- }
216
- catch (error) {
217
- this.logger?.error?.('MSW: Analytics metadata failed', error);
218
- const message = error instanceof Error ? error.message : 'Unknown error';
219
- return {
220
- status: 400,
221
- data: { error: message }
222
- };
223
- }
224
- }
225
- static async triggerAutomation(request) {
226
- if (!this.protocol) {
227
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
228
- }
229
- this.logger?.debug?.('MSW: Triggering automation', { request });
230
- try {
231
- const result = await this.protocol.triggerAutomation(request);
232
- this.logger?.info?.('MSW: Automation triggered', { result });
233
- return {
234
- status: 200,
235
- data: result
236
- };
237
- }
238
- catch (error) {
239
- this.logger?.error?.('MSW: Automation trigger failed', error);
240
- const message = error instanceof Error ? error.message : 'Unknown error';
241
- return {
242
- status: 400,
243
- data: { error: message }
244
- };
245
- }
246
- }
247
- // Legacy method names for compatibility
248
- static async getUser(id) {
249
- return this.getData('user', id);
250
- }
251
- static async createUser(data) {
252
- return this.createData('user', data);
253
- }
254
- static async saveMetaItem(type, name, item) {
255
- if (!this.protocol) {
256
- throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init() first.');
257
- }
258
- this.logger?.debug?.('MSW: Saving metadata', { type, name });
259
- try {
260
- // Check if protocol supports saveMetaItem (it might be added recently)
261
- if (!this.protocol.saveMetaItem) {
262
- throw new Error('Protocol does not support saveMetaItem');
263
- }
264
- const result = await this.protocol.saveMetaItem({ type, name, item });
265
- this.logger?.info?.('MSW: Metadata saved', { type, name });
266
- return {
267
- status: 200,
268
- data: result
269
- };
270
- }
271
- catch (error) {
272
- this.logger?.error?.('MSW: Save metadata failed', error, { type, name });
273
- const message = error instanceof Error ? error.message : 'Unknown error';
274
- return {
275
- status: 400,
276
- data: { error: message }
277
- };
278
- }
279
- }
280
- }
281
- ObjectStackServer.protocol = null;
282
- ObjectStackServer.logger = null;
283
46
  /**
284
47
  * MSW Plugin for ObjectStack
48
+
285
49
  *
286
50
  * This plugin enables Mock Service Worker integration for testing and development.
287
51
  * It automatically mocks API endpoints using the ObjectStack runtime protocol.
@@ -376,272 +140,76 @@ export class MSWPlugin {
376
140
  * Setup MSW handlers
377
141
  */
378
142
  setupHandlers(ctx) {
379
- if (!this.protocol) {
380
- ctx.logger.warn('[MSWPlugin] Protocol not initialized. Skipping default API handlers.');
381
- this.handlers = [
382
- ...(this.options.customHandlers || [])
383
- ];
384
- return;
143
+ // Initialize HttpDispatcher
144
+ try {
145
+ this.dispatcher = new HttpDispatcher(ctx.getKernel());
146
+ }
147
+ catch (e) {
148
+ ctx.logger.warn('[MSWPlugin] Could not initialize HttpDispatcher via Kernel. Falling back to simple handlers.');
385
149
  }
386
- const protocol = this.protocol;
387
- // Initialize ObjectStackServer with structured logger
388
- ObjectStackServer.init(protocol, this.options.logRequests ? ctx.logger : undefined);
389
- ctx.logger.debug('Initialized ObjectStackServer', { logRequests: this.options.logRequests });
390
150
  const baseUrl = this.options.baseUrl || '/api/v1';
391
- // Define standard ObjectStack API handlers
151
+ // Custom handlers have priority
392
152
  this.handlers = [
393
- // Discovery endpoint
394
- http.get(`${baseUrl}`, async () => {
395
- const discovery = await protocol.getDiscovery({});
396
- return HttpResponse.json({
397
- ...discovery,
398
- routes: {
399
- data: `${baseUrl}/data`,
400
- metadata: `${baseUrl}/meta`,
401
- ui: `${baseUrl}/ui`,
402
- auth: `${baseUrl}/auth`
403
- }
404
- });
405
- }),
406
- // Meta endpoints
407
- http.get(`${baseUrl}/meta`, async ({ request }) => {
408
- const url = new URL(request.url);
409
- const query = parseQueryParams(url);
410
- return HttpResponse.json(await protocol.getMetaTypes({ query }));
411
- }),
412
- http.get(`${baseUrl}/meta/:type`, async ({ params, request }) => {
153
+ ...(this.options.customHandlers || [])
154
+ ];
155
+ if (this.dispatcher) {
156
+ const dispatcher = this.dispatcher;
157
+ // Catch-all handler for ObjectStack Runtime
158
+ // We use a wildcard to capture all methods and paths under baseUrl
159
+ const catchAll = async ({ request, params }) => {
413
160
  const url = new URL(request.url);
414
- const query = parseQueryParams(url);
415
- return HttpResponse.json(await protocol.getMetaItems({ type: params.type, query }));
416
- }),
417
- http.get(`${baseUrl}/meta/:type/:name`, async ({ params }) => {
418
- try {
419
- return HttpResponse.json(await protocol.getMetaItem({ type: params.type, name: params.name }));
420
- }
421
- catch (error) {
422
- const message = error instanceof Error ? error.message : 'Unknown error';
423
- return HttpResponse.json({ error: message }, { status: 404 });
424
- }
425
- }),
426
- // Save Metadata
427
- http.put(`${baseUrl}/meta/:type/:name`, async ({ params, request }) => {
428
- try {
429
- const body = await request.json();
430
- const result = await ObjectStackServer.saveMetaItem(params.type, params.name, body);
431
- return HttpResponse.json(result.data, { status: result.status });
432
- }
433
- catch (error) {
434
- const message = error instanceof Error ? error.message : 'Unknown error';
435
- return HttpResponse.json({ error: message }, { status: 400 });
436
- }
437
- }),
438
- // Data endpoints
439
- http.get(`${baseUrl}/data/:object`, async ({ params, request }) => {
440
- try {
441
- const url = new URL(request.url);
442
- // Use helper to parse properly (handle multiple values, JSON strings, numbers)
443
- const rawParams = parseQueryParams(url);
444
- // Normalize to standard query object (move flats to 'where')
445
- const queryParams = normalizeQuery(rawParams);
446
- const result = await ObjectStackServer.findData(params.object, queryParams);
447
- return HttpResponse.json(result.data, {
448
- status: result.status,
449
- headers: { 'Cache-Control': 'no-store' }
450
- });
451
- }
452
- catch (error) {
453
- const message = error instanceof Error ? error.message : 'Unknown error';
454
- return HttpResponse.json({ error: message }, { status: 404 });
455
- }
456
- }),
457
- http.get(`${baseUrl}/data/:object/:id`, async ({ params }) => {
458
- try {
459
- const result = await ObjectStackServer.getData(params.object, params.id);
460
- return HttpResponse.json(result.data, {
461
- status: result.status,
462
- headers: { 'Cache-Control': 'no-store' }
463
- });
464
- }
465
- catch (error) {
466
- const message = error instanceof Error ? error.message : 'Unknown error';
467
- return HttpResponse.json({ error: message }, { status: 404 });
468
- }
469
- }),
470
- http.post(`${baseUrl}/data/:object`, async ({ params, request }) => {
471
- try {
472
- const body = await request.json();
473
- const result = await ObjectStackServer.createData(params.object, body);
474
- return HttpResponse.json(result.data, { status: result.status });
475
- }
476
- catch (error) {
477
- const message = error instanceof Error ? error.message : 'Unknown error';
478
- return HttpResponse.json({ error: message }, { status: 400 });
479
- }
480
- }),
481
- http.patch(`${baseUrl}/data/:object/:id`, async ({ params, request }) => {
482
- try {
483
- const body = await request.json();
484
- const result = await ObjectStackServer.updateData(params.object, params.id, body);
485
- return HttpResponse.json(result.data, { status: result.status });
486
- }
487
- catch (error) {
488
- const message = error instanceof Error ? error.message : 'Unknown error';
489
- return HttpResponse.json({ error: message }, { status: 400 });
490
- }
491
- }),
492
- http.delete(`${baseUrl}/data/:object/:id`, async ({ params }) => {
493
- try {
494
- const result = await ObjectStackServer.deleteData(params.object, params.id);
495
- return HttpResponse.json(result.data, { status: result.status });
496
- }
497
- catch (error) {
498
- const message = error instanceof Error ? error.message : 'Unknown error';
499
- return HttpResponse.json({ error: message }, { status: 400 });
500
- }
501
- }),
502
- // Batch Operations
503
- http.post(`${baseUrl}/data/:object/batch`, async ({ params, request }) => {
504
- try {
505
- const body = await request.json();
506
- const result = await protocol.batchData({ object: params.object, request: body });
507
- return HttpResponse.json(result);
508
- }
509
- catch (error) {
510
- const message = error instanceof Error ? error.message : 'Unknown error';
511
- return HttpResponse.json({ error: message }, { status: 400 });
512
- }
513
- }),
514
- http.post(`${baseUrl}/data/:object/createMany`, async ({ params, request }) => {
515
- try {
516
- const body = await request.json();
517
- const records = Array.isArray(body) ? body : [];
518
- const result = await protocol.createManyData({ object: params.object, records });
519
- return HttpResponse.json(result, { status: 201 });
520
- }
521
- catch (error) {
522
- const message = error instanceof Error ? error.message : 'Unknown error';
523
- return HttpResponse.json({ error: message }, { status: 400 });
524
- }
525
- }),
526
- http.post(`${baseUrl}/data/:object/updateMany`, async ({ params, request }) => {
527
- try {
528
- const body = await request.json();
529
- const result = await protocol.updateManyData({
530
- object: params.object,
531
- records: body?.records || [],
532
- options: body?.options
533
- });
534
- return HttpResponse.json(result);
535
- }
536
- catch (error) {
537
- const message = error instanceof Error ? error.message : 'Unknown error';
538
- return HttpResponse.json({ error: message }, { status: 400 });
539
- }
540
- }),
541
- http.post(`${baseUrl}/data/:object/deleteMany`, async ({ params, request }) => {
542
- try {
543
- const body = await request.json();
544
- const result = await protocol.deleteManyData({
545
- object: params.object,
546
- ids: body?.ids || [],
547
- options: body?.options
548
- });
549
- return HttpResponse.json(result);
550
- }
551
- catch (error) {
552
- const message = error instanceof Error ? error.message : 'Unknown error';
553
- return HttpResponse.json({ error: message }, { status: 400 });
554
- }
555
- }),
556
- // Enhanced Metadata with Cache Support
557
- http.get(`${baseUrl}/meta/:type/:name`, async ({ params, request }) => {
558
- try {
559
- const cacheRequest = {
560
- ifNoneMatch: request.headers.get('if-none-match') || undefined,
561
- ifModifiedSince: request.headers.get('if-modified-since') || undefined,
562
- };
563
- const result = await protocol.getMetaItemCached({
564
- type: params.type,
565
- name: params.name,
566
- cacheRequest
567
- });
568
- if (result.notModified) {
569
- return new HttpResponse(null, { status: 304 });
161
+ // Calculate path relative to API prefix
162
+ // e.g. /api/v1/data/contacts -> /data/contacts
163
+ let path = url.pathname;
164
+ if (path.startsWith(baseUrl)) {
165
+ path = path.slice(baseUrl.length);
166
+ }
167
+ // Parse Body if present
168
+ let body = undefined;
169
+ if (request.method !== 'GET' && request.method !== 'HEAD') {
170
+ try {
171
+ body = await request.clone().json();
570
172
  }
571
- // Build response headers
572
- const headers = {};
573
- if (result.etag) {
574
- const etagValue = result.etag.weak ? `W/"${result.etag.value}"` : `"${result.etag.value}"`;
575
- headers['ETag'] = etagValue;
173
+ catch (e) {
174
+ try {
175
+ // Try form data if json fails?
176
+ // Dispatcher expects objects usually.
177
+ // For file upload, body might be FormData logic needed?
178
+ // For now assume JSON or text
179
+ }
180
+ catch (e2) { }
576
181
  }
577
- if (result.lastModified) {
578
- headers['Last-Modified'] = new Date(result.lastModified).toUTCString();
182
+ }
183
+ // Parse Query
184
+ const query = parseQueryParams(url);
185
+ // Dispatch
186
+ const result = await dispatcher.dispatch(request.method, path, body, query, { request });
187
+ if (result.handled) {
188
+ if (result.response) {
189
+ return HttpResponse.json(result.response.body, {
190
+ status: result.response.status,
191
+ headers: result.response.headers
192
+ });
579
193
  }
580
- if (result.cacheControl) {
581
- const directives = result.cacheControl.directives.join(', ');
582
- const maxAge = result.cacheControl.maxAge ? `, max-age=${result.cacheControl.maxAge}` : '';
583
- headers['Cache-Control'] = directives + maxAge;
194
+ if (result.result) {
195
+ // Handle special results (streams/redirects - unlikely in MSW but possible)
196
+ if (result.result.type === 'redirect') {
197
+ return HttpResponse.redirect(result.result.url);
198
+ }
199
+ // Fallback for others
200
+ return HttpResponse.json(result.result);
584
201
  }
585
- return HttpResponse.json(result.data, { headers });
586
- }
587
- catch (error) {
588
- const message = error instanceof Error ? error.message : 'Unknown error';
589
- return HttpResponse.json({ error: message }, { status: 404 });
590
- }
591
- }),
592
- // UI Protocol endpoint
593
- http.get(`${baseUrl}/ui/view/:object`, async ({ params, request }) => {
594
- try {
595
- const url = new URL(request.url);
596
- const viewType = url.searchParams.get('type') || 'list';
597
- const view = await protocol.getUiView({ object: params.object, type: viewType });
598
- return HttpResponse.json(view);
599
- }
600
- catch (error) {
601
- const message = error instanceof Error ? error.message : 'Unknown error';
602
- return HttpResponse.json({ error: message }, { status: 404 });
603
- }
604
- }),
605
- // Analytics Operations
606
- http.post(`${baseUrl}/analytics/query`, async ({ request }) => {
607
- try {
608
- const body = await request.json();
609
- const result = await ObjectStackServer.analyticsQuery(body);
610
- return HttpResponse.json(result.data, { status: result.status });
611
- }
612
- catch (error) {
613
- const message = error instanceof Error ? error.message : 'Unknown error';
614
- return HttpResponse.json({ error: message }, { status: 400 });
615
- }
616
- }),
617
- http.get(`${baseUrl}/analytics/meta`, async ({ request }) => {
618
- try {
619
- const url = new URL(request.url);
620
- const query = parseQueryParams(url);
621
- const result = await ObjectStackServer.getAnalyticsMeta(query);
622
- return HttpResponse.json(result.data, { status: result.status });
623
- }
624
- catch (error) {
625
- const message = error instanceof Error ? error.message : 'Unknown error';
626
- return HttpResponse.json({ error: message }, { status: 400 });
627
- }
628
- }),
629
- // Automation Operations
630
- http.post(`${baseUrl}/automation/trigger`, async ({ request }) => {
631
- try {
632
- const body = await request.json();
633
- const result = await ObjectStackServer.triggerAutomation(body);
634
- return HttpResponse.json(result.data, { status: result.status });
635
- }
636
- catch (error) {
637
- const message = error instanceof Error ? error.message : 'Unknown error';
638
- return HttpResponse.json({ error: message }, { status: 400 });
639
202
  }
640
- }),
641
- // Add custom handlers
642
- ...(this.options.customHandlers || [])
643
- ];
644
- ctx.logger.info('MSW request handlers installed', { count: this.handlers.length, baseUrl });
203
+ // Not handled by dispatcher (404 for this route subset)
204
+ return undefined; // Let MSW pass through or handle next
205
+ };
206
+ this.handlers.push(http.all(`${baseUrl}/*`, catchAll), http.all(`${baseUrl}`, catchAll) // Handle root if needed
207
+ );
208
+ ctx.logger.info('MSW handlers set up using HttpDispatcher', { baseUrl });
209
+ }
210
+ else {
211
+ ctx.logger.warn('[MSWPlugin] No dispatcher available. No API routes registered.');
212
+ }
645
213
  }
646
214
  /**
647
215
  * Start the MSW worker
@@ -682,3 +250,37 @@ export class MSWPlugin {
682
250
  return this.handlers;
683
251
  }
684
252
  }
253
+ /**
254
+ * Static helper for interacting with ObjectStack protocol in MSW handlers
255
+ */
256
+ export class ObjectStackServer {
257
+ static init(protocol) {
258
+ this.protocol = protocol;
259
+ }
260
+ static getProtocol() {
261
+ if (!this.protocol) {
262
+ throw new Error('ObjectStackServer not initialized. Call ObjectStackServer.init(protocol) first.');
263
+ }
264
+ return this.protocol;
265
+ }
266
+ static async findData(objectName, query) {
267
+ const body = await this.getProtocol().findData({ object: objectName, query });
268
+ return { data: body, status: 200 };
269
+ }
270
+ static async getData(objectName, id) {
271
+ const body = await this.getProtocol().getData({ object: objectName, id });
272
+ return { data: body, status: 200 };
273
+ }
274
+ static async createData(objectName, data) {
275
+ const body = await this.getProtocol().createData({ object: objectName, data });
276
+ return { data: body, status: 201 };
277
+ }
278
+ static async updateData(objectName, id, data) {
279
+ const body = await this.getProtocol().updateData({ object: objectName, id, data });
280
+ return { data: body, status: 200 };
281
+ }
282
+ static async deleteData(objectName, id) {
283
+ const body = await this.getProtocol().deleteData({ object: objectName, id });
284
+ return { data: body, status: 200 };
285
+ }
286
+ }
package/package.json CHANGED
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "name": "@objectstack/plugin-msw",
3
- "version": "1.0.1",
3
+ "version": "1.0.4",
4
4
  "description": "MSW (Mock Service Worker) Plugin for ObjectStack Runtime",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "peerDependencies": {
9
- "@objectstack/runtime": "^1.0.1"
9
+ "@objectstack/runtime": "^1.0.4"
10
10
  },
11
11
  "dependencies": {
12
12
  "msw": "^2.0.0",
13
- "@objectstack/spec": "1.0.1",
14
- "@objectstack/types": "1.0.1",
15
- "@objectstack/objectql": "1.0.1"
13
+ "@objectstack/core": "1.0.4",
14
+ "@objectstack/objectql": "1.0.4",
15
+ "@objectstack/spec": "1.0.4",
16
+ "@objectstack/types": "1.0.4"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@types/node": "^25.1.0",
19
20
  "typescript": "^5.0.0",
20
21
  "vitest": "^4.0.18",
21
- "@objectstack/runtime": "1.0.1"
22
+ "@objectstack/runtime": "1.0.4"
22
23
  },
23
24
  "scripts": {
24
25
  "build": "tsc",