Skip to content

Commit 2f838d7

Browse files
Copilothotlong
andcommitted
fix: enrich MSW object metadata with listViews from stack config
The ObjectStack runtime protocol strips listViews from object metadata during Zod validation in defineStack(). The MSW handlers now re-attach listViews from the pre-defineStack sharedConfig so the console can resolve named views (calendar, kanban, etc.) for each object. Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent a219bc7 commit 2f838d7

File tree

3 files changed

+57
-12
lines changed

3 files changed

+57
-12
lines changed

apps/console/src/mocks/browser.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import { ObjectKernel } from '@objectstack/runtime';
1111
import { InMemoryDriver } from '@objectstack/driver-memory';
1212
import { setupWorker } from 'msw/browser';
13-
import appConfig from '../../objectstack.shared';
13+
import appConfig, { sharedConfig } from '../../objectstack.shared';
1414
import { createKernel } from './createKernel';
1515
import { createHandlers } from './handlers';
1616

@@ -42,8 +42,10 @@ export async function startMockServer() {
4242
// Create MSW handlers that match the response format of HonoServerPlugin
4343
// Include both /api/v1 and legacy /api paths so the ObjectStackClient can
4444
// reach the mock server regardless of which base URL it probes.
45-
const v1Handlers = createHandlers('/api/v1', kernel, driver);
46-
const legacyHandlers = createHandlers('/api', kernel, driver);
45+
// Pass sharedConfig (pre-defineStack) so handlers can enrich object metadata
46+
// with listViews that defineStack's Zod parse strips.
47+
const v1Handlers = createHandlers('/api/v1', kernel, driver, sharedConfig);
48+
const legacyHandlers = createHandlers('/api', kernel, driver, sharedConfig);
4749
const handlers = [...v1Handlers, ...legacyHandlers];
4850

4951
// Start MSW service worker

apps/console/src/mocks/handlers.ts

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,26 @@ import { http, HttpResponse } from 'msw';
1515
/**
1616
* Create MSW request handlers for a given base URL.
1717
*
18-
* @param baseUrl - URL prefix, e.g. '/api/v1' (browser) or 'http://localhost:3000/api/v1' (node)
19-
* @param kernel - Bootstrapped ObjectKernel with protocol service
20-
* @param driver - InMemoryDriver for direct data access
18+
* @param baseUrl - URL prefix, e.g. '/api/v1' (browser) or 'http://localhost:3000/api/v1' (node)
19+
* @param kernel - Bootstrapped ObjectKernel with protocol service
20+
* @param driver - InMemoryDriver for direct data access
21+
* @param appConfig - Original stack config (used to enrich protocol responses with listViews)
2122
*/
22-
export function createHandlers(baseUrl: string, kernel: ObjectKernel, driver: InMemoryDriver) {
23+
export function createHandlers(baseUrl: string, kernel: ObjectKernel, driver: InMemoryDriver, appConfig?: any) {
2324
const protocol = kernel.getService('protocol') as any;
2425

26+
// Build a lookup of listViews by object name from the original config.
27+
// The runtime protocol strips listViews from object metadata, so we
28+
// re-attach them here to ensure the console can resolve named views.
29+
const listViewsByObject: Record<string, Record<string, any>> = {};
30+
if (appConfig?.objects) {
31+
for (const obj of appConfig.objects) {
32+
if (obj.listViews && Object.keys(obj.listViews).length > 0) {
33+
listViewsByObject[obj.name] = obj.listViews;
34+
}
35+
}
36+
}
37+
2538
// Determine whether we're in a browser (relative paths, wildcard prefix)
2639
// or in Node.js tests (absolute URLs)
2740
const isBrowser = !baseUrl.startsWith('http');
@@ -56,11 +69,25 @@ export function createHandlers(baseUrl: string, kernel: ObjectKernel, driver: In
5669
http.get(`${prefix}${baseUrl}/meta/:type`, async ({ params }) => {
5770
const metadataType = params.type as string;
5871
const response = await protocol.getMetaItems({ type: metadataType });
72+
// Enrich object metadata with listViews from stack config
73+
if ((metadataType === 'object' || metadataType === 'objects') && response?.items) {
74+
response.items = response.items.map((obj: any) => {
75+
const views = listViewsByObject[obj.name];
76+
return views ? { ...obj, listViews: { ...(obj.listViews || {}), ...views } } : obj;
77+
});
78+
}
5979
return HttpResponse.json(response, { status: 200 });
6080
}),
6181
http.get(`${prefix}${baseUrl}/metadata/:type`, async ({ params }) => {
6282
const metadataType = params.type as string;
6383
const response = await protocol.getMetaItems({ type: metadataType });
84+
// Enrich object metadata with listViews from stack config
85+
if ((metadataType === 'object' || metadataType === 'objects') && response?.items) {
86+
response.items = response.items.map((obj: any) => {
87+
const views = listViewsByObject[obj.name];
88+
return views ? { ...obj, listViews: { ...(obj.listViews || {}), ...views } } : obj;
89+
});
90+
}
6491
return HttpResponse.json(response, { status: 200 });
6592
}),
6693

@@ -71,7 +98,14 @@ export function createHandlers(baseUrl: string, kernel: ObjectKernel, driver: In
7198
type: params.type as string,
7299
name: params.name as string
73100
});
74-
const payload = (response && response.item) ? response.item : response;
101+
let payload = (response && response.item) ? response.item : response;
102+
// Enrich single object with listViews from stack config
103+
if ((params.type === 'object' || params.type === 'objects') && payload && payload.name) {
104+
const views = listViewsByObject[payload.name];
105+
if (views) {
106+
payload = { ...payload, listViews: { ...(payload.listViews || {}), ...views } };
107+
}
108+
}
75109
return HttpResponse.json(payload || { error: 'Not found' }, { status: payload ? 200 : 404 });
76110
} catch (e) {
77111
return HttpResponse.json({ error: String(e) }, { status: 500 });
@@ -83,7 +117,14 @@ export function createHandlers(baseUrl: string, kernel: ObjectKernel, driver: In
83117
type: params.type as string,
84118
name: params.name as string
85119
});
86-
const payload = (response && response.item) ? response.item : response;
120+
let payload = (response && response.item) ? response.item : response;
121+
// Enrich single object with listViews from stack config
122+
if ((params.type === 'object' || params.type === 'objects') && payload && payload.name) {
123+
const views = listViewsByObject[payload.name];
124+
if (views) {
125+
payload = { ...payload, listViews: { ...(payload.listViews || {}), ...views } };
126+
}
127+
}
87128
return HttpResponse.json(payload || { error: 'Not found' }, { status: payload ? 200 : 404 });
88129
} catch (e) {
89130
return HttpResponse.json({ error: String(e) }, { status: 500 });

apps/console/src/mocks/server.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import { ObjectKernel } from '@objectstack/runtime';
1111
import { InMemoryDriver } from '@objectstack/driver-memory';
1212
import { setupServer } from 'msw/node';
13-
import appConfig from '../../objectstack.shared';
13+
import appConfig, { sharedConfig } from '../../objectstack.shared';
1414
import { createKernel } from './createKernel';
1515
import { createHandlers } from './handlers';
1616

@@ -31,8 +31,10 @@ export async function startMockServer() {
3131
driver = result.driver;
3232

3333
// Create MSW handlers for both paths to ensure compatibility with client defaults
34-
const v1Handlers = createHandlers('http://localhost:3000/api/v1', kernel, driver);
35-
const legacyHandlers = createHandlers('http://localhost:3000/api', kernel, driver);
34+
// Pass sharedConfig (pre-defineStack) so handlers can enrich object metadata
35+
// with listViews that defineStack's Zod parse strips.
36+
const v1Handlers = createHandlers('http://localhost:3000/api/v1', kernel, driver, sharedConfig);
37+
const legacyHandlers = createHandlers('http://localhost:3000/api', kernel, driver, sharedConfig);
3638
const handlers = [...v1Handlers, ...legacyHandlers];
3739

3840
// Setup MSW server for Node.js environment

0 commit comments

Comments
 (0)