Skip to content

Commit fbce620

Browse files
committed
新增 REST API 协议文档和发现协议相关的 Zod 模式定义
1 parent 732b96d commit fbce620

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed

content/docs/specifications/server/meta.cn.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"automation-rules",
88
"audit-compliance",
99
"integration-etl",
10+
"rest-api",
1011
"plugin-manifest"
1112
]
1213
}

content/docs/specifications/server/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"automation-rules",
88
"audit-compliance",
99
"integration-etl",
10+
"rest-api",
1011
"plugin-manifest"
1112
]
1213
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: REST API Protocol
3+
description: 标准 Data API 与 Metadata API 接口规范
4+
---
5+
6+
# REST API Protocol
7+
8+
ObjectStack 遵循 "Protocol First" 原则,提供了一套标准化的 RESTful API,用于前端与 ObjectOS 内核进行交互。
9+
10+
为了解决硬编码 URL 路径的问题,ObjectStack 引入了 **Discovery Protocol(发现协议)**。客户端应首先请求发现端点,获取当前环境的所有服务入口。
11+
12+
## 1. Discovery (入口发现)
13+
14+
客户端启动时(如 `App.init`),应首先请求此端点。
15+
16+
- **Endpoint**: `GET /.well-known/objectstack``GET /api/v1/discovery`
17+
- **Response Type**: `DiscoveryResponse`
18+
19+
```json
20+
{
21+
"name": "Acme CRM Production",
22+
"version": "1.0.0",
23+
"environment": "production",
24+
"routes": {
25+
"data": "/api/v1/data",
26+
"metadata": "/api/v1/meta",
27+
"auth": "/api/v1/auth",
28+
"actions": "/api/v1/actions",
29+
"storage": "/api/v1/storage",
30+
"graphql": "/api/v1/graphql"
31+
},
32+
"features": {
33+
"graphql": true,
34+
"search": true,
35+
"files": true
36+
},
37+
"locale": {
38+
"default": "zh-CN",
39+
"supported": ["en-US", "zh-CN"],
40+
"timezone": "Asia/Shanghai"
41+
}
42+
}
43+
```
44+
45+
## 2. Standard Data API (数据操作)
46+
47+
基于 `routes.data` 返回的基路径(默认为 `/api/v1/data`)。
48+
49+
### 查询对象记录 (Query)
50+
51+
- **Method**: `GET /:objectName`
52+
- **Params**:
53+
- `select`: 字段列表(逗号分隔)
54+
- `filter`: 过滤条件(JSON string, try `filters` in QuerySchema)
55+
- `sort`: 排序(如 `created_at desc`
56+
- `page`: 页码
57+
- `pageSize`: 每页数量
58+
59+
### 获取单条记录 (Retrieve)
60+
61+
- **Method**: `GET /:objectName/:recordId`
62+
63+
### 创建记录 (Create)
64+
65+
- **Method**: `POST /:objectName`
66+
- **Body**: Record data object
67+
68+
### 更新记录 (Update)
69+
70+
- **Method**: `PATCH /:objectName/:recordId`
71+
- **Body**: Changed fields
72+
73+
### 删除记录 (Delete)
74+
75+
- **Method**: `DELETE /:objectName/:recordId`
76+
77+
## 3. Standard Metadata API (元数据)
78+
79+
基于 `routes.metadata` 返回的基路径(默认为 `/api/v1/meta`)。
80+
81+
### 获取所有对象定义
82+
83+
- **Method**: `GET /objects`
84+
- **Response**: List of `ObjectSchema` (summary)
85+
86+
### 获取特定对象定义
87+
88+
- **Method**: `GET /objects/:objectName`
89+
- **Response**: Full `ObjectSchema` (incl. fields, validation)
90+
91+
### 获取应用导航菜单
92+
93+
- **Method**: `GET /menus`
94+
- **Response**: `MenuItem[]`
95+
96+
## 4. Custom API Endpoints
97+
98+
开发者可以通过 `ApiEndpointSchema` 定义自定义的 API 接口,这些接口通常挂载在 `/api/v1/custom` 下或自定义路径。
99+
100+
详见 [Custom API Guide](/docs/specifications/server/custom-api).
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: REST API Protocol
3+
description: Standard Data API and Metadata API Specification
4+
---
5+
6+
# REST API Protocol
7+
8+
ObjectStack follows the "Protocol First" principle, providing a set of standardized RESTful APIs for interaction between the frontend and the ObjectOS kernel.
9+
10+
To solve the problem of hardcoded URL paths, ObjectStack introduces the **Discovery Protocol**, Clients should first request the discovery endpoint to obtain service entry points for the current environment.
11+
12+
## 1. Discovery
13+
14+
When the client starts (e.g., `App.init`), it should first request this endpoint.
15+
16+
- **Endpoint**: `GET /.well-known/objectstack` or `GET /api/v1/discovery`
17+
- **Response Type**: `DiscoveryResponse`
18+
19+
```json
20+
{
21+
"name": "Acme CRM Production",
22+
"version": "1.0.0",
23+
"environment": "production",
24+
"routes": {
25+
"data": "/api/v1/data",
26+
"metadata": "/api/v1/meta",
27+
"auth": "/api/v1/auth",
28+
"actions": "/api/v1/actions",
29+
"storage": "/api/v1/storage",
30+
"graphql": "/api/v1/graphql"
31+
},
32+
"features": {
33+
"graphql": true,
34+
"search": true,
35+
"files": true
36+
},
37+
"locale": {
38+
"default": "en-US",
39+
"supported": ["en-US", "zh-CN"],
40+
"timezone": "America/Los_Angeles"
41+
}
42+
}
43+
```
44+
45+
## 2. Standard Data API
46+
47+
Based on the base path returned by `routes.data` (default is `/api/v1/data`).
48+
49+
### Query Objects (Query)
50+
51+
- **Method**: `GET /:objectName`
52+
- **Params**:
53+
- `select`: List of fields (comma separated)
54+
- `filter`: Filter criteria (JSON string, see `filters` in QuerySchema)
55+
- `sort`: Sorting (e.g. `created_at desc`)
56+
- `page`: Page number
57+
- `pageSize`: Items per page
58+
59+
### Get Single Record (Retrieve)
60+
61+
- **Method**: `GET /:objectName/:recordId`
62+
63+
### Create Record (Create)
64+
65+
- **Method**: `POST /:objectName`
66+
- **Body**: Record data object
67+
68+
### Update Record (Update)
69+
70+
- **Method**: `PATCH /:objectName/:recordId`
71+
- **Body**: Changed fields
72+
73+
### Delete Record (Delete)
74+
75+
- **Method**: `DELETE /:objectName/:recordId`
76+
77+
## 3. Standard Metadata API
78+
79+
Based on the base path returned by `routes.metadata` (default is `/api/v1/meta`).
80+
81+
### Get All Object Definitions
82+
83+
- **Method**: `GET /objects`
84+
- **Response**: List of `ObjectSchema` (summary)
85+
86+
### Get Specific Object Definition
87+
88+
- **Method**: `GET /objects/:objectName`
89+
- **Response**: Full `ObjectSchema` (incl. fields, validation)
90+
91+
### Get App Navigation Menus
92+
93+
- **Method**: `GET /menus`
94+
- **Response**: `MenuItem[]`
95+
96+
## 4. Custom API Endpoints
97+
98+
Developers can define custom API interfaces via `ApiEndpointSchema`, which are typically mounted under `/api/v1/custom` or a custom path.
99+
100+
See [Custom API Guide](/docs/specifications/server/custom-api).

packages/spec/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ export * from './system/webhook.zod';
4343
export * from './system/translation.zod';
4444
export * from './system/constants';
4545
export * from './system/types';
46+
export * from './system/discovery.zod';
4647

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* API Capabilities Schema
5+
* Defines what features are enabled on this ObjectOS instance.
6+
*/
7+
export const ApiCapabilitiesSchema = z.object({
8+
graphql: z.boolean().default(false),
9+
search: z.boolean().default(false),
10+
websockets: z.boolean().default(false),
11+
files: z.boolean().default(true),
12+
});
13+
14+
/**
15+
* API Routes Schema
16+
* The "Map" for the frontend to know where to send requests.
17+
* This decouples the frontend from hardcoded URL paths.
18+
*/
19+
export const ApiRoutesSchema = z.object({
20+
/** Base URL for Object CRUD (Standard Data API) */
21+
data: z.string().describe('e.g. /api/v1/data'),
22+
23+
/** Base URL for Schema Definitions (Metadata API) */
24+
metadata: z.string().describe('e.g. /api/v1/meta'),
25+
26+
/** Base URL for Authentication */
27+
auth: z.string().describe('e.g. /api/v1/auth'),
28+
29+
/** Base URL for Server Actions/Flows */
30+
actions: z.string().optional().describe('e.g. /api/v1/p'),
31+
32+
/** Base URL for File/Storage operations */
33+
storage: z.string().optional().describe('e.g. /api/v1/storage'),
34+
35+
/** GraphQL Endpoint (if enabled) */
36+
graphql: z.string().optional().describe('e.g. /api/v1/graphql'),
37+
});
38+
39+
/**
40+
* Discovery Response Schema
41+
* The root object returned by the Metadata Discovery Endpoint.
42+
*/
43+
export const DiscoverySchema = z.object({
44+
/** System Identity */
45+
name: z.string(),
46+
version: z.string(),
47+
environment: z.enum(['production', 'sandbox', 'development']),
48+
49+
/** Dynamic Routing */
50+
routes: ApiRoutesSchema,
51+
52+
/** Feature Flags */
53+
features: ApiCapabilitiesSchema,
54+
55+
/** Localization Info (helping frontend init i18n) */
56+
locale: z.object({
57+
default: z.string(),
58+
supported: z.array(z.string()),
59+
timezone: z.string(),
60+
}),
61+
});
62+
63+
export type DiscoveryResponse = z.infer<typeof DiscoverySchema>;
64+
export type ApiRoutes = z.infer<typeof ApiRoutesSchema>;
65+
export type ApiCapabilities = z.infer<typeof ApiCapabilitiesSchema>;

0 commit comments

Comments
 (0)