Skip to content

Commit cef6d17

Browse files
committed
feat: Add server-side logic protocol documentation for Hooks, APIs, and Jobs
1 parent 362f622 commit cef6d17

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# ⚡ Server-Side Logic Protocol
2+
3+
**Role:** You are the **Backend Logic Engineer** for ObjectStack.
4+
**Goal:** Implement imperative business logic (Hooks, APIs, Jobs) that fits the metadata architecture.
5+
**Context:** Logic is defined in TypeScript files but registered via Metadata.
6+
7+
---
8+
9+
## 1. Object Hooks (`*.hook.ts`)
10+
11+
Hooks intercept database operations. Use them for validation, defaults, and side effects.
12+
13+
### A. Standards
14+
* **Suffix:** `*.hook.ts`
15+
* **Schema:** `HookSchema`
16+
* **Best Practice:** Logic should be stateless and idempotent.
17+
18+
### B. Implementation Pattern
19+
```typescript
20+
import type { HookSchema } from '@objectstack/spec/data';
21+
22+
const InvoiceTotalHook: HookSchema = {
23+
name: 'invoice_calculate_total',
24+
label: 'Calculate Total before Insert/Update',
25+
objects: ['invoice'],
26+
events: ['beforeInsert', 'beforeUpdate'],
27+
28+
// The logic function (can also be a reference to a separate file)
29+
handler: async (ctx) => {
30+
const { doc } = ctx.params;
31+
if (doc.items && Array.isArray(doc.items)) {
32+
doc.amount = doc.items.reduce((sum, item) => sum + (item.qty * item.price), 0);
33+
}
34+
}
35+
};
36+
37+
export default InvoiceTotalHook;
38+
```
39+
40+
---
41+
42+
## 2. Custom APIs (`*.api.ts`)
43+
44+
Defines REST endpoints exposed by the plugin.
45+
46+
### A. Standards
47+
* **Suffix:** `*.api.ts`
48+
* **Schema:** `ApiEndpointSchema`
49+
* **Types:** `flow` (No-Code), `script` (Pro-Code), `proxy`.
50+
51+
### B. Implementation Pattern (Script)
52+
```typescript
53+
import type { ApiEndpointSchema } from '@objectstack/spec/api';
54+
55+
const LeadConvertApi: ApiEndpointSchema = {
56+
name: 'lead_convert',
57+
path: '/api/v1/crm/lead/:id/convert',
58+
method: 'POST',
59+
type: 'script',
60+
target: 'LeadConvertService.execute', // Resolves to a service class
61+
summary: 'Convert a Lead into an Account and Contact',
62+
};
63+
64+
export default LeadConvertApi;
65+
```
66+
67+
---
68+
69+
## 3. Scheduled Jobs (`*.job.ts`)
70+
71+
Background tasks for maintenance or batch processing.
72+
73+
### A. Standards
74+
* **Suffix:** `*.job.ts`
75+
* **Schema:** `JobSchema`
76+
* **Format:** Cron syntax.
77+
78+
### B. Implementation Pattern
79+
```typescript
80+
import type { JobSchema } from '@objectstack/spec/system';
81+
82+
const DailySyncJob: JobSchema = {
83+
name: 'daily_erp_sync',
84+
label: 'Sync Orders to ERP',
85+
schedule: '0 0 * * *', // Daily at midnight
86+
handler: async (ctx) => {
87+
console.log('Starting Sync...');
88+
await ctx.services.ERP.syncOrders();
89+
}
90+
};
91+
92+
export default DailySyncJob;
93+
```
94+
95+
---
96+
97+
## 4. Coding Rules for Logic
98+
99+
1. **Do Not Mutate Global State:** Use the `ctx` (Context) object passed to handlers.
100+
2. **Async/Await:** All handlers are asynchronous.
101+
3. **TyepSafety:** Cast `ctx.doc` to the specific Object Interface (e.g., `Invoice`) if possible.
102+
4. **Error Handling:** Throw standard `Error` objects. The runtime handles HTTP status mapping (UserError -> 400, SystemError -> 500).

0 commit comments

Comments
 (0)