mcpField
A
appdb

appdb

github.com/stahuraData & databases24193 installsUpdated 26w ago
Repository

About appdb

appdb is a guide for Domo App Platform developers using AppDBClient from @domoinc/toolkit to manage collection documents and interpret query responses.

Key features

  1. 01CRUD operations with AppDBClient
  2. 02Conditional queries and bulk updates
  3. 03Parse app fields from document content
  4. 04Declare collections in manifest.json

Use cases

  1. 01Create and maintain collection data in Domo apps
  2. 02Filter documents by status or priority
  3. 03Shape query results for app interfaces

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/stahura/domo-ai-vibe-rules --skill appdb

After installing, type/appdbin Claude Code to confirm it loaded.

Details

From the project README

Rule: Domo App Platform AppDB (Toolkit-First)

This rule is toolkit-first. Use AppDBClient instead of raw domo.get/post/put/delete endpoints.

Canonical Client

yarn add @domoinc/toolkit
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
const created = await tasksClient.create({
  title: 'New Task',
  status: 'active',
  priority: 'High'
});
const task = created.body;
Read / query
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)

Documents returned by .get() are wrapped with metadata and your fields live inside doc.content.

What .create() accepts:

{ vendor: 'Acme', riskLevel: 'High', notes: 'Late payments' }

What .get() returns (shape):

[
  {
    "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:

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:

// WRONG: fields are inside content
const docs = response.body || response;
docs[0].vendor; // undefined

// CORRECT
docs[0].content.vendor; // "Acme"
Update
await tasksClient.update({
  id: 'document-uuid',
  content: { title: 'Updated', status: 'completed', priority: 'Low' }
});

await tasksClient.partialUpdate(
  { status: { $eq: 'active' } },
  { $set: { status: 'archived' } }
);
Delete
await tasksClient.delete('document-uuid');
await tasksClient.delete(['uuid-1', 'uuid-2']);

Manifest Requirements

Collections still must exist in manifest.json under collections.

{
  "collections": [
    {
      "name": "TasksCollection",
      "schema": {
        "columns": [
          { "name": "title", "type": "STRING" },
          { "name": "status", "type": "STRING" }
        ]
      }
    }
  ]
}

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

Comments

Markdown supported