Skip to content

Commit 5acafe3

Browse files
committed
Add engine development context documentation outlining the ObjectStack Runtime architecture and implementation patterns
1 parent 94d31f4 commit 5acafe3

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# ⚙️ ObjectStack Runtime Engine Development Context
2+
3+
**Role:** You are the **Core Framework Engineer** for ObjectStack.
4+
**Task:** Build the React-based Server-Driven UI (SDUI) Engine that interprets Zod Metadata and renders the UI.
5+
**Environment:** A frontend application (e.g., Next.js, Vite) consuming the `@objectstack/spec` package.
6+
7+
---
8+
9+
## 1. The Trinity of Engines
10+
11+
A complete ObjectUI Runtime consists of three coordinating engines. Each engine consumes specific types from `@objectstack/spec`.
12+
13+
### A. Layout Engine (`<PageRenderer />`)
14+
Responsible for recursive rendering of the UI tree.
15+
* **Input Protocol:** `Page` (from `@objectstack/spec/ui`)
16+
* *Reference:* `packages/spec/src/ui/page.zod.ts`
17+
* **Block Protocol:** `PageComponent` (from `@objectstack/spec/ui`)
18+
* *Reference:* `packages/spec/src/ui/block.zod.ts`
19+
* **Logic:**
20+
1. Recursively traverse `Page.regions` and `Region.components`.
21+
2. Map `component.type` (e.g., `page:tabs`) to the React Component via `widgetRegistry`.
22+
3. Pass `component.properties` as Props (Typed as `ComponentProps` from `@objectstack/spec/ui`).
23+
4. Inject `context` (Record ID, User Info) into the component tree.
24+
* **Key Hook:** `useComponentResolver(type)`
25+
26+
### B. Data Engine (`useObjectData()`)
27+
Responsible for data fetching, caching, and state management.
28+
* **Input Protocol:** `View` / `ListView` (from `@objectstack/spec/ui`)
29+
* *Reference:* `packages/spec/src/ui/view.zod.ts`
30+
* **Filter Protocol:** `FilterCondition` (from `@objectstack/spec/data`)
31+
* *Reference:* `packages/spec/src/data/filter.zod.ts`
32+
* **Library:** React Query (TanStack Query) + SWR.
33+
* **Logic:**
34+
1. Convert `View.filters` and `View.sort` into ObjectQL Query.
35+
2. Handle `isLoading`, `error`, `data` states.
36+
3. Provide `refresh()` and `mutations` (Create/Update/Delete).
37+
* **Key Hook:** `useRecord(object, id)`, `useList(object, view)`
38+
39+
### C. Action Engine (`useAction()`)
40+
Responsible for executing business logic and side effects.
41+
* **Input Protocol:** `Action` (from `@objectstack/spec/ui`)
42+
* *Reference:* `packages/spec/src/ui/action.zod.ts`
43+
* **Logic:**
44+
1. **Pre-check:** Evaluate `disabled` state and permissions.
45+
2. **Confirmation:** Show Modal if `confirmText` is present.
46+
3. **Execution:** Call API / Run Script / Navigate URL.
47+
4. **Feedback:** Show Toast (Success/Error) and trigger `DataEngine.refresh()`.
48+
49+
---
50+
51+
## 2. Standard Contexts
52+
53+
Your engine must provide these React Contexts to all widgets:
54+
55+
### `ObjectContext`
56+
* **Definition:** `@objectstack/spec/data` -> `ObjectSchema`
57+
* Current `objectName` (e.g., "project_task")
58+
* Field definitions (Schema)
59+
60+
### `RecordContext`
61+
* Current `recordId`
62+
* Live record data (e.g., `{ id: "123", name: "Fix Bug" }`)
63+
* Permissions (`allowEdit`, `allowDelete`)
64+
65+
### `UIContext`
66+
* **Definition:** `@objectstack/spec/ui` -> `ThemeSchema`
67+
* Device State (`isMobile`)
68+
* Theme Config (`mode: 'dark' | 'light'`)
69+
* Navigation Helpers (`openModal`, `navigate`)
70+
71+
---
72+
73+
## 3. Implementation Patterns
74+
75+
### The Resolver Pattern (for PageRenderer)
76+
```typescript
77+
import { Page, PageComponent } from '@objectstack/spec/ui';
78+
79+
function PageRenderer({ schema }: { schema: Page }) {
80+
return (
81+
<div className="page-layout">
82+
{schema.regions.map(region => (
83+
<div key={region.name} className={`region-${region.width}`}>
84+
{region.components.map((block: PageComponent) => (
85+
<ComponentBlock key={block.id} config={block} />
86+
))}
87+
</div>
88+
))}
89+
</div>
90+
);
91+
}
92+
```
93+
94+
### The HoC Pattern (for Widget Enrichment)
95+
Wrap every widget in a Higher-Order Component to handle common logic:
96+
```typescript
97+
import { PageComponent } from '@objectstack/spec/ui';
98+
99+
function withEngine(Widget: React.ComponentType) {
100+
return (props: { config: PageComponent }) => {
101+
// 1. Auto-handle Visibility
102+
if (!evalVisibility(props.config.visibility)) return null;
103+
104+
// 2. Error Boundary
105+
return (
106+
<ErrorBoundary>
107+
<Suspense fallback={<AtomSpinner />}>
108+
<Widget {...props} />
109+
</Suspense>
110+
</ErrorBoundary>
111+
);
112+
};
113+
}
114+
```

0 commit comments

Comments
 (0)