Giao diện
API reference
Widget resource — uiWidgets
uiWidgets:findOne
Lấy widget theo UID.
GET /api/uiWidgets:findOne?filter[uid]=<widgetUid>Response:
json
{
"data": {
"uid": "w1",
"name": "dashboard-chart",
"options": { "chartType": "bar", "dataSource": "orders" }
}
}uiWidgets:schema
Lấy schema đơn lẻ của widget (không bao gồm descendants).
GET /api/uiWidgets:schema?uid=<widgetUid>uiWidgets:schemas
Lấy nhiều schema cùng lúc.
GET /api/uiWidgets:schemas?uids[]=w1&uids[]=w2uiWidgets:schemaBundle
Lấy schema bundle — widget gốc kèm toàn bộ descendants tree.
GET /api/uiWidgets:schemaBundle?uid=<widgetUid>Response chứa schema dạng nested JSON tree, bao gồm tất cả children ở mọi depth.
uiWidgets:save
Lưu widget (tạo mới nếu UID chưa tồn tại, cập nhật nếu đã có).
POST /api/uiWidgets:save
Body: {
"uid": "w_new",
"name": "my-chart",
"options": { "chartType": "line" }
}uiWidgets:duplicate
Nhân bản widget kèm toàn bộ descendants. Sinh UID mới cho tất cả node.
POST /api/uiWidgets:duplicate
Body: {
"uid": "w1",
"targetParentUid": "w_parent",
"position": "afterEnd"
}| Param | Mô tả |
|---|---|
uid | UID widget cần nhân bản |
targetParentUid | UID parent đích (nếu khác parent hiện tại) |
position | Vị trí: beforeBegin, afterBegin, beforeEnd, afterEnd |
uiWidgets:attach
Gắn widget (đã tồn tại) vào parent tại vị trí chỉ định.
POST /api/uiWidgets:attach
Body: {
"uid": "w_detached",
"targetParentUid": "w_parent",
"position": "beforeEnd"
}uiWidgets:move
Di chuyển widget sang parent khác. Cập nhật toàn bộ closure paths.
POST /api/uiWidgets:move
Body: {
"uid": "w3",
"targetParentUid": "w_new_parent",
"position": "afterBegin"
}uiWidgets:destroy
Xóa widget kèm tất cả descendants.
DELETE /api/uiWidgets:destroy?uid=<widgetUid>uiWidgets:mutate
Batch operations — thực hiện nhiều thay đổi trong một transaction.
POST /api/uiWidgets:mutate
Body: {
"operations": [
{ "type": "save", "uid": "w1", "options": { "title": "Updated" } },
{ "type": "destroy", "uid": "w_old" },
{ "type": "move", "uid": "w3", "targetParentUid": "w1", "position": "afterEnd" }
]
}Variables — variables
variables:resolve
Resolve danh sách biến template thành giá trị thực tế.
POST /api/variables:resolve
Body: {
"variables": [
"ctx.currentUser.id",
"ctx.currentUser.nickname",
"ctx.currentTime"
]
}Response:
json
{
"data": {
"ctx.currentUser.id": 5,
"ctx.currentUser.nickname": "Admin",
"ctx.currentTime": "2025-06-15T10:30:00Z"
}
}Lưu ý: Cú pháp biến sử dụng dạng path string (VD:
ctx.currentUser.id). Phía client dùng cú pháp mustache để nhúng biến vào template, nhưng server nhận path string qua API.
Query Service — queryService
queryService:run
Chạy query trực tiếp.
POST /api/queryService:run
Body: {
"dataSourceKey": "main",
"sql": "SELECT id, title FROM orders WHERE status = :status",
"params": { "status": "pending" }
}SQL được xử lý qua transformSQL (sanitize) và parseLiquidContext (resolve biến Liquid) trước khi thực thi.
queryService:runById
Chạy query đã lưu theo UID.
POST /api/queryService:runById
Body: {
"uid": "q1",
"params": { "status": "pending" }
}queryService:save
Lưu query để tái sử dụng.
POST /api/queryService:save
Body: {
"uid": "q_orders_pending",
"dataSourceKey": "main",
"sql": "SELECT id, title FROM orders WHERE status = :status"
}queryService:getBind
Lấy data binding — ánh xạ giữa query result columns và widget fields.
GET /api/queryService:getBind?uid=<queryUid>Response:
json
{
"data": {
"queryUid": "q1",
"bindings": {
"id": "rowKey",
"title": "label",
"amount": "value"
}
}
}Ví dụ sử dụng
Tạo widget và gắn vào parent
typescript
await agent.resource('uiWidgets').save({
values: {
uid: 'w_chart_1',
name: 'sales-chart',
options: { chartType: 'bar', dataSourceKey: 'main' },
},
});
await agent.resource('uiWidgets').attach({
values: {
uid: 'w_chart_1',
targetParentUid: 'w_dashboard',
position: 'beforeEnd',
},
});Resolve biến và chạy query
typescript
const vars = await agent.resource('variables').resolve({
values: {
variables: ['ctx.currentUser.id'],
},
});
const userId = vars.body.data['ctx.currentUser.id'];
const data = await agent.resource('queryService').run({
values: {
dataSourceKey: 'main',
sql: 'SELECT * FROM orders WHERE created_by_id = :userId',
params: { userId },
},
});