cap-apps-appdb
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRule: Domo App Platform AppDB (Toolkit-First)
规则:Domo App Platform AppDB(优先使用工具包)
This rule is toolkit-first. Use instead of raw endpoints.
AppDBClientdomo.get/post/put/deleteLegacy endpoint-first guidance has been archived to.archive/legacy-rules/domo-appdb.md
本规则遵循优先使用工具包原则。请使用而非原生的端点。
AppDBClientdomo.get/post/put/delete旧版优先使用端点的指南已归档至。archive/legacy-rules/domo-appdb.md
Canonical Client
标准客户端
bash
yarn add @domoinc/toolkittypescript
import { AppDBClient } from '@domoinc/toolkit';
type Task = {
title: string;
status: 'active' | 'completed';
priority: 'Low' | 'High' | 'Urgent';
};
const tasksClient = new AppDBClient.DocumentsClient<Task>('TasksCollection');bash
yarn add @domoinc/toolkittypescript
import { AppDBClient } from '@domoinc/toolkit';
type Task = {
title: string;
status: 'active' | 'completed';
priority: 'Low' | 'High' | 'Urgent';
};
const tasksClient = new AppDBClient.DocumentsClient<Task>('TasksCollection');Core Operations
核心操作
Create
创建
typescript
const created = await tasksClient.create({
title: 'New Task',
status: 'active',
priority: 'High'
});
const task = created.body;typescript
const created = await tasksClient.create({
title: 'New Task',
status: 'active',
priority: 'High'
});
const task = created.body;Read / query
读取 / 查询
typescript
const all = await tasksClient.get();
const active = await tasksClient.get({ status: { $eq: 'active' } });
const highOpen = await tasksClient.get({
$and: [{ status: { $ne: 'completed' } }, { priority: { $in: ['High', 'Urgent'] } }]
});typescript
const all = await tasksClient.get();
const active = await tasksClient.get({ status: { $eq: 'active' } });
const highOpen = await tasksClient.get({
$and: [{ status: { $ne: 'completed' } }, { priority: { $in: ['High', 'Urgent'] } }]
});AppDB response structure (critical)
AppDB响应结构(重点)
Documents returned by are wrapped with metadata and your fields live inside .
.get()doc.contentWhat accepts:
.create()typescript
{ vendor: 'Acme', riskLevel: 'High', notes: 'Late payments' }What returns (shape):
.get()json
[
{
"id": "04b1756e-7b6d-4d77-842f-7975a6474d8a",
"datastoreId": "a3b85171-...",
"collectionId": "ba194a7d-...",
"syncRequired": true,
"owner": 767612617,
"createdOn": "2026-03-22T02:22:42.030Z",
"updatedOn": "2026-03-22T02:22:42.030Z",
"updatedBy": 767612617,
"content": {
"vendor": "Acme",
"riskLevel": "High",
"notes": "Late payments"
}
}
]Key points:
- Your app fields are nested inside , not at the top level.
doc.content - is the document ID used for
doc.idand.update()..delete() - Metadata fields (,
datastoreId,collectionId,owner, etc.) are top-level.createdOn - Overall result may be in or directly the array.
response.body
Required parsing pattern:
typescript
const response = await tasksClient.get();
const rawDocs = response.body || response;
const docs = Array.isArray(rawDocs) ? rawDocs : [];
const parsed = docs.map((doc) => ({
id: doc.id,
...doc.content
}));Common mistake:
typescript
// WRONG: fields are inside content
const docs = response.body || response;
docs[0].vendor; // undefined
// CORRECT
docs[0].content.vendor; // "Acme".get()doc.content.create()typescript
{ vendor: 'Acme', riskLevel: 'High', notes: 'Late payments' }.get()json
[
{
"id": "04b1756e-7b6d-4d77-842f-7975a6474d8a",
"datastoreId": "a3b85171-...",
"collectionId": "ba194a7d-...",
"syncRequired": true,
"owner": 767612617,
"createdOn": "2026-03-22T02:22:42.030Z",
"updatedOn": "2026-03-22T02:22:42.030Z",
"updatedBy": 767612617,
"content": {
"vendor": "Acme",
"riskLevel": "High",
"notes": "Late payments"
}
}
]关键点:
- 你的应用字段嵌套在中,而非顶层。
doc.content - 是用于
doc.id和.update()的文档ID。.delete() - 元数据字段(、
datastoreId、collectionId、owner等)位于顶层。createdOn - 整体结果可能在中,也可能直接是数组。
response.body
必填解析模式:
typescript
const response = await tasksClient.get();
const rawDocs = response.body || response;
const docs = Array.isArray(rawDocs) ? rawDocs : [];
const parsed = docs.map((doc) => ({
id: doc.id,
...doc.content
}));常见错误:
typescript
// 错误:字段在content内部
const docs = response.body || response;
docs[0].vendor; // undefined
// 正确
docs[0].content.vendor; // "Acme"Update
更新
typescript
await tasksClient.update({
id: 'document-uuid',
content: { title: 'Updated', status: 'completed', priority: 'Low' }
});
await tasksClient.partialUpdate(
{ status: { $eq: 'active' } },
{ $set: { status: 'archived' } }
);typescript
await tasksClient.update({
id: 'document-uuid',
content: { title: 'Updated', status: 'completed', priority: 'Low' }
});
await tasksClient.partialUpdate(
{ status: { $eq: 'active' } },
{ $set: { status: 'archived' } }
);Delete
删除
typescript
await tasksClient.delete('document-uuid');
await tasksClient.delete(['uuid-1', 'uuid-2']);typescript
await tasksClient.delete('document-uuid');
await tasksClient.delete(['uuid-1', 'uuid-2']);Manifest Requirements
清单要求
Collections still must exist in under .
manifest.jsoncollectionsjson
{
"collections": [
{
"name": "TasksCollection",
"schema": {
"columns": [
{ "name": "title", "type": "STRING" },
{ "name": "status", "type": "STRING" }
]
}
}
]
}集合仍必须在的下定义。
manifest.jsoncollectionsjson
{
"collections": [
{
"name": "TasksCollection",
"schema": {
"columns": [
{ "name": "title", "type": "STRING" },
{ "name": "status", "type": "STRING" }
]
}
}
]
}Canonical Rules References
标准规则参考
- Toolkit AppDB patterns:
.cursor/rules/04-toolkit.mdc - AppDB gotchas and sync caveats:
.cursor/rules/09-gotchas.mdc
- 工具包AppDB模式:
.cursor/rules/04-toolkit.mdc - AppDB注意事项与同步警告:
.cursor/rules/09-gotchas.mdc
Checklist
检查清单
- mapping exists in manifest
collections - used for CRUD
AppDBClient.DocumentsClient - results are unwrapped from
.get()before UI/usedoc.content - Query/update operators (,
$eq,$in,$set, etc.) used correctly$inc - Error handling and loading states included in UI flows
- 清单中存在映射
collections - 使用执行CRUD操作
AppDBClient.DocumentsClient - 在UI使用前,从中解析
doc.content的结果.get() - 正确使用查询/更新操作符(、
$eq、$in、$set等)$inc - UI流程中包含错误处理与加载状态