cap-apps-appdb

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rule: Domo App Platform AppDB (Toolkit-First)

规则:Domo App Platform AppDB(优先使用工具包)

This rule is toolkit-first. Use
AppDBClient
instead of raw
domo.get/post/put/delete
endpoints.
Legacy endpoint-first guidance has been archived to
archive/legacy-rules/domo-appdb.md
.
本规则遵循优先使用工具包原则。请使用
AppDBClient
而非原生的
domo.get/post/put/delete
端点。
旧版优先使用端点的指南已归档至
archive/legacy-rules/domo-appdb.md

Canonical Client

标准客户端

bash
yarn add @domoinc/toolkit
typescript
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/toolkit
typescript
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
.get()
are wrapped with metadata and your fields live inside
doc.content
.
What
.create()
accepts:
typescript
{ vendor: 'Acme', riskLevel: 'High', notes: 'Late payments' }
What
.get()
returns (shape):
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
    doc.content
    , not at the top level.
  • doc.id
    is the document ID used for
    .update()
    and
    .delete()
    .
  • Metadata fields (
    datastoreId
    ,
    collectionId
    ,
    owner
    ,
    createdOn
    , etc.) are top-level.
  • Overall result may be in
    response.body
    or directly the array.
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()
    .delete()
    的文档ID。
  • 元数据字段(
    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
manifest.json
under
collections
.
json
{
  "collections": [
    {
      "name": "TasksCollection",
      "schema": {
        "columns": [
          { "name": "title", "type": "STRING" },
          { "name": "status", "type": "STRING" }
        ]
      }
    }
  ]
}
集合仍必须在
manifest.json
collections
下定义。
json
{
  "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

检查清单

  • collections
    mapping exists in manifest
  • AppDBClient.DocumentsClient
    used for CRUD
  • .get()
    results are unwrapped from
    doc.content
    before UI/use
  • Query/update operators (
    $eq
    ,
    $in
    ,
    $set
    ,
    $inc
    , etc.) used correctly
  • Error handling and loading states included in UI flows
  • 清单中存在
    collections
    映射
  • 使用
    AppDBClient.DocumentsClient
    执行CRUD操作
  • 在UI使用前,从
    doc.content
    中解析
    .get()
    的结果
  • 正确使用查询/更新操作符(
    $eq
    $in
    $set
    $inc
    等)
  • UI流程中包含错误处理与加载状态