domo-js
Use ryuu.js (domo.js) APIs for env, events, navigation, and data calls.
How do I install this agent skill?
npx skills add https://github.com/stahura/domo-ai-vibe-rules --skill domo-jsIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides documentation and code examples for using the Domo (ryuu.js) SDK. It covers environment access, event listeners, navigation, and data retrieval using standard library functions. No malicious patterns or security risks were detected.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
- ZeroLeakspass
Score: 93/100 · 2 sections analyzed
What does this agent skill do?
domo.js (ryuu.js) SDK
Installing domo.js (ryuu.js)
React / npm projects:
npm install ryuu.js
import domo from 'ryuu.js';
Vanilla JavaScript (CDN):
<script src="https://app.unpkg.com/ryuu.js@5.1.2"></script>
domo.js Utilities
Beyond the APIs, domo.js provides useful utilities for interacting with the Domo environment:
Environment Info
Access environment information. WARNING: Can be spoofed! Do not use for security.
console.log(domo.env.userId); // User ID (spoofable!)
console.log(domo.env.customer); // Customer/instance name
console.log(domo.env.pageId); // Current page ID
console.log(domo.env.locale); // Locale (e.g., 'en-US')
console.log(domo.env.platform); // 'desktop' or 'mobile'
For secure user verification:
// ✅ SECURE - Server-verified identity
const verifiedEnv = await domo.get('/domo/environment/v1/');
const { userId, userName, userEmail } = verifiedEnv;
// Or use IdentityClient from toolkit
import { IdentityClient } from '@domoinc/toolkit';
const response = await IdentityClient.get();
const user = response.body; // { id, displayName, emailAddress, role }
Event Listeners
Dataset Updates
domo.onDataUpdated((alias) => {
console.log(`Dataset ${alias} was updated`);
// Refresh your data or do nothing to prevent auto-reload
});
Page Filter Changes (onFiltersUpdated / onFiltersUpdate)
Fires when native filter cards on the same App Studio page (or dashboard) change. Register at the top level — outside any React component or useEffect.
Use onFiltersUpdate when available on newer ryuu.js versions, and fall back to onFiltersUpdated for compatibility.
const registerFilterListener = (handler) => {
try {
if (typeof domo.onFiltersUpdate === "function") return domo.onFiltersUpdate(handler);
if (typeof domo.onFiltersUpdated === "function") return domo.onFiltersUpdated(handler);
} catch (_) {
// Listener registry can be uninitialized in some runtimes.
}
};
registerFilterListener((filters) => {
if (!Array.isArray(filters) || filters.length === 0) return;
filters.forEach(({ column, operand, values, dataType }) => {
switch (column?.toUpperCase()) {
case "YEAR_OF_EVENT":
if (operand === "BETWEEN" && values?.length === 2) {
state.yearRange = { min: Number(values[0]), max: Number(values[1]) };
} else if (operand === "IN" && values.length > 0) {
const nums = values.map(Number).sort((a, b) => a - b);
state.yearRange = { min: nums[0], max: nums[nums.length - 1] };
}
break;
case "CATEGORY":
if (operand === "IN") {
state.categories = values.length > 0 ? values : ["ALL"];
}
break;
}
});
fetchData(); // Refetch immediately — no "apply" step for page filters
});
Filter object shape — each element in the filters array:
| Field | Type | Values |
|---|---|---|
column | string | Dataset column name |
operand | string | BETWEEN, IN, GREATER_THAN_EQUAL, LESS_THAN_EQUAL, EQUALS |
values | array | For BETWEEN: [min, max]. For IN: selected values. For scalar: [value]. |
dataType | string | LONG, STRING, DATE, etc. |
The field is operand, not operator. Incoming filters use operand. Outgoing filters (via requestFiltersUpdate) use operator. This asymmetry is a known Domo API inconsistency.
Variable Changes (onVariablesUpdated)
Fires when App Studio variable controls change. Variables are identified by numeric string IDs. Register at the top level.
domo.onVariablesUpdated((variables) => {
if (!variables || typeof variables !== "object") return;
const typeVar = variables["860"];
if (typeVar?.parsedExpression?.value) {
const label = typeVar.parsedExpression.value; // display label, e.g., "Cumulative"
state.pendingType = MY_LABEL_MAP[label]; // map to internal value
}
updateUI(); // Show pending state, don't refetch yet — wait for Apply
});
Variable object shape — variables is keyed by numeric function ID strings:
{
"858": { "parsedExpression": { "exprType": "LITERAL", "value": "Year Sold" } },
"860": { "parsedExpression": { "exprType": "LITERAL", "value": "Cumulative" } }
}
Variables deliver display labels that need mapping to internal values. Use a pending/commit pattern: store in staging state on change, commit and refetch only when the user clicks Apply.
Update Variables Programmatically (requestVariablesUpdate)
Write App Studio variables from within a custom app. Primary use: dependent dropdowns — when variable A changes, set variable B.
domo.requestVariablesUpdate(
[{ functionId: 873, value: "Initial Service" }],
(ack) => { console.log("acknowledged"); },
(reply) => { console.log("completed"); }
);
Loop prevention: Updating a variable fires onVariablesUpdated again. Guard with a flag:
state.isUpdatingVariable = true;
domo.requestVariablesUpdate(updates, onAck, (reply) => {
state.isUpdatingVariable = false;
});
// In onVariablesUpdated: if (state.isUpdatingVariable) return;
The payload uses functionId (a number), not a string. The callbacks are onAck (queued) and onReply (completed).
Navigation
Important: Standard anchor tags with href do NOT work properly in Domo apps. You must use domo.navigate():
// Navigate within Domo
domo.navigate('/page/123456789');
// Open in new tab
domo.navigate('/page/123456789', true);
// External URLs also work
domo.navigate('https://example.com', true);
Fetch Multiple Datasets
// Load multiple datasets in parallel
const [sales, customers, products] = await domo.getAll([
'/data/v1/sales',
'/data/v1/customers',
'/data/v1/products'
]);
Update Page Filters Programmatically
domo.requestFiltersUpdate(
[
{
column: 'category',
operator: 'IN',
values: ['Electronics', 'Clothing'],
dataType: 'STRING'
}
],
true, // apply to page
() => console.log('Filter update acknowledged'),
(response) => console.log('Filter update completed:', response)
);
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/stahura/domo-ai-vibe-rules/domo-js">View domo-js on skillZs</a>