Skip to content

Commit 5404fda

Browse files
Copilothotlong
andcommitted
Remove @example/app-crm and @example/app-todo dependencies from studio; load apps dynamically from objectstack.config.ts
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 41d9784 commit 5404fda

7 files changed

Lines changed: 58 additions & 26 deletions

File tree

apps/studio/objectstack.config.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,40 @@ export const TaskObject = {
1919
fields: {
2020
id: { name: 'id', label: 'ID', type: 'text', required: true },
2121
subject: { name: 'subject', label: 'Subject', type: 'text', required: true },
22-
priority: { name: 'priority', label: 'Priority', type: 'number', defaultValue: 5 },
22+
status: {
23+
name: 'status',
24+
label: 'Status',
25+
type: 'select',
26+
options: [
27+
{ label: 'Not Started', value: 'not_started' },
28+
{ label: 'In Progress', value: 'in_progress' },
29+
{ label: 'Waiting', value: 'waiting' },
30+
{ label: 'Completed', value: 'completed' },
31+
]
32+
},
33+
priority: {
34+
name: 'priority',
35+
label: 'Priority',
36+
type: 'select',
37+
options: [
38+
{ label: 'Low', value: 'low' },
39+
{ label: 'Normal', value: 'normal' },
40+
{ label: 'High', value: 'high' },
41+
{ label: 'Urgent', value: 'urgent' },
42+
]
43+
},
44+
category: { name: 'category', label: 'Category', type: 'text' },
45+
due_date: { name: 'due_date', label: 'Due Date', type: 'date' },
2346
is_completed: { name: 'is_completed', label: 'Completed', type: 'boolean', defaultValue: false },
2447
created_at: { name: 'created_at', label: 'Created At', type: 'datetime' }
2548
}
2649
};
2750

2851
/**
2952
* App Configuration
53+
*
54+
* This is the single source of truth for apps/studio in MSW (browser) mode.
55+
* In server mode the studio fetches apps dynamically via the API.
3056
*/
3157
export default defineStack({
3258
name: 'task_app',
@@ -41,6 +67,23 @@ export default defineStack({
4167
objects: [
4268
TaskObject
4369
],
70+
data: [
71+
{
72+
object: 'task',
73+
mode: 'upsert' as const,
74+
externalId: 'subject',
75+
records: [
76+
{ subject: 'Learn ObjectStack', status: 'completed', priority: 'high', category: 'Work' },
77+
{ subject: 'Build a cool app', status: 'in_progress', priority: 'normal', category: 'Work' },
78+
{ subject: 'Review PR #102', status: 'completed', priority: 'high', category: 'Work' },
79+
{ subject: 'Write Documentation', status: 'not_started', priority: 'normal', category: 'Work' },
80+
{ subject: 'Fix Server bug', status: 'waiting', priority: 'urgent', category: 'Work' },
81+
{ subject: 'Buy groceries', status: 'not_started', priority: 'low', category: 'Shopping' },
82+
{ subject: 'Schedule dentist appointment', status: 'not_started', priority: 'normal', category: 'Health' },
83+
{ subject: 'Pay utility bills', status: 'not_started', priority: 'high', category: 'Finance' },
84+
]
85+
}
86+
],
4487
navigation: [
4588
{
4689
id: 'group_tasks',

apps/studio/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
"preview": "vite preview"
1818
},
1919
"dependencies": {
20-
"@example/app-crm": "workspace:*",
21-
"@example/app-todo": "workspace:*",
2220
"@objectstack/client": "workspace:*",
2321
"@objectstack/client-react": "workspace:*",
2422
"@objectstack/driver-memory": "workspace:*",

apps/studio/src/mocks/browser.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@
66
* This creates a complete ObjectStack environment in the browser using the In-Memory Driver
77
* and the MSW Plugin which automatically exposes the API.
88
*
9-
* NOTE: The console does NOT hardcode a list of app packages. The app list is
10-
* fetched dynamically from the server API via `GET /api/v1/meta/apps`.
11-
* The imports here are only used to boot the in-browser kernel (MSW mode).
9+
* App configs are loaded dynamically from objectstack.config.ts at the project root.
10+
* The UI itself fetches apps via `GET /api/v1/meta/apps` — not from these imports.
1211
*/
1312
import { ObjectKernel } from '@objectstack/runtime';
14-
import todoConfig from '@example/app-todo/objectstack.config';
15-
import crmConfig from '@example/app-crm/objectstack.config';
13+
import studioConfig from '../../objectstack.config';
1614
import { createKernel } from './createKernel';
1715

1816
let kernel: ObjectKernel | null = null;
@@ -43,20 +41,19 @@ function resolveConfig(raw: any) {
4341
}
4442

4543
/**
46-
* App configs used ONLY for kernel bootstrapping in MSW (browser) mode.
44+
* Boot config loaded dynamically from objectstack.config.ts.
4745
* The UI never reads this directly — it discovers apps via the meta API.
4846
*/
4947
const bootConfigs = [
50-
resolveConfig(todoConfig),
51-
resolveConfig(crmConfig),
48+
resolveConfig(studioConfig),
5249
];
5350

5451
export async function startMockServer() {
5552
if (kernel) return;
5653

5754
console.log('[MSW] Starting ObjectStack Runtime (Browser Mode)...');
5855

59-
// Use shared factory with multi-app support
56+
// Use shared factory app list comes from objectstack.config.ts
6057
kernel = await createKernel({
6158
appConfigs: bootConfigs,
6259
enableBrowser: true

apps/studio/src/mocks/simulateBrowser.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { createKernel } from './createKernel';
44
import { setupServer } from 'msw/node';
55
import { http, HttpResponse } from 'msw';
66
import { ObjectStackClient } from '@objectstack/client';
7-
import todoConfig from '@example/app-todo/objectstack.config';
7+
import studioConfig from '../../objectstack.config';
88

99
/**
1010
* Creates a Realistic Browser Simulation
@@ -16,8 +16,8 @@ import todoConfig from '@example/app-todo/objectstack.config';
1616
* 4. Returns a ready-to-use Client
1717
*/
1818
export async function simulateBrowser() {
19-
// 1. Boot Kernel (Headless Mode)
20-
const appConfig = (todoConfig as any).default || todoConfig;
19+
// 1. Boot Kernel (Headless Mode) — config loaded from objectstack.config.ts
20+
const appConfig = (studioConfig as any).default || studioConfig;
2121
const kernel = await createKernel({
2222
appConfig,
2323
enableBrowser: false // Disable the built-in browser MSW worker

apps/studio/test/verify-dom.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('DOM Simulation', () => {
2727
fieldCount: Object.keys(def.fields || {}).length
2828
});
2929

30-
expect(def.name).toBe('todo__task');
30+
expect(def.name).toBe('task');
3131
expect(Object.keys(def.fields).length).toBeGreaterThan(0);
3232

3333
// 2. Fetch Data (short name resolves via engine.resolveObjectName)

apps/studio/test/verify-metadata.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ describe('Metadata Service Integration', () => {
2525
expect(Array.isArray(objects)).toBe(true);
2626
expect(objects.length).toBeGreaterThan(0);
2727

28-
// FQN uses double underscore: todo__task
29-
const todoTask = objects.find((o: any) => o.name === 'todo__task');
30-
expect(todoTask).toBeDefined();
28+
// Object name without namespace prefix (studio config has no namespace)
29+
const task = objects.find((o: any) => o.name === 'task');
30+
expect(task).toBeDefined();
3131
});
3232

3333
it('should fetch object details via client.meta.getItem("object", ...)', async () => {
@@ -37,7 +37,7 @@ describe('Metadata Service Integration', () => {
3737
const def = response.data || response;
3838

3939
expect(def).toBeDefined();
40-
expect(def.name).toBe('todo__task');
40+
expect(def.name).toBe('task');
4141
expect(def.fields).toBeDefined();
4242

4343
// Check if fields are parsed correctly (client might return Map or Object depending on version)

pnpm-lock.yaml

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)