Expert assistant for building Node.js applications using the OpenIAP platform. Enforces coding conventions, guides database operations, event handling, and work item queue management with the OpenIAP client library.
Expert assistant for building Node.js applications using the OpenIAP platform with proper conventions and best practices.
Guides developers in writing Node.js code that integrates with OpenIAP's MongoDB database, message queues, work item queues, and event system. Enforces proper coding conventions, connection lifecycle management, and API usage patterns specific to the OpenIAP client library.
When the user needs to interact with OpenIAP's database:
1. Import and initialize the OpenIAP client:
```js
const { Client } = require("openiap");
const client = new Client();
await client.connect();
```
2. Always establish connection before any database operations
For code that must reinitialize state on reconnection (queue registration, watches, etc.):
1. Create an `onConnected()` function containing initialization logic
2. Hook into the client event stream to call it on `SignedIn` events
3. **Always call this AFTER `connect()`** — you will still receive the initial `Connected` and `SignedIn` events
```js
await client.connect();
client.on_client_event((event) => {
if (event && event.event === "SignedIn") {
onConnected().catch((error) => {
client.error(error);
});
}
});
async function onConnected() {
const queuename = client.register_queue({ queuename: queue }, (event) => {
// Handle incoming event
});
}
```
Use these methods for CRUD operations on OpenIAP MongoDB:
**Query & Aggregation:**
**Insert & Update:**
**Delete:**
Work item queues contain units of work to be processed. **Critical state management:**
```js
// Push work item
client.push_workitem({ wiq, wiqid, name, payload, nextrun, success_wiqid, failed_wiqid, success_wiq, failed_wiq, priority, files })
// Pop work item for processing
client.pop_workitem({ wiq, wiqid, downloadfolder })
// Update work item state (REQUIRED after processing)
client.update_workitem({ workitem, ignoremaxretries, files })
// Delete work item
client.delete_workitem(id)
```
**Watch (Change Streams):**
```js
// Monitor collection changes (insert, update, delete)
client.watch({ collectionname, paths }, (event, event_counter) => {
const { id, operation, document } = event;
// Handle change
});
client.unwatch(watchid);
```
**Queue Messaging:**
```js
// Register queue and handle messages (returns queuename)
client.register_queue({ queuename }, ({ queuename, correlation_id, replyto, routingkey, exchangename, data }) => {
// Handle message
});
// Register exchange and handle messages (returns queuename)
client.register_exchange({ exchangename, algorithm, routingkey, addqueue }, (event) => {
// Handle message
});
// Unregister queue
client.unregister_queue(queuename);
// Send message to queue or exchange
client.queue_message({ queuename, data, replyto, exchangename, correlation_id, routingkey, striptoken, expiration });
// Send message and wait for reply (RPC pattern)
const response = await client.rpc({ queuename, data, striptoken });
```
```js
// Upload file
client.upload({ filepath, filename, mimetype, metadata, collectionname });
// Download file
client.download({ collectionname, id, folder, filename });
```
```js
client.signin({ username, password, jwt, agent, version, longtoken, validateonly, ping });
client.connect();
client.disconnect();
```
**NEVER use `console.log()` or `console.debug()`**
Always use OpenIAP logging functions:
Enable tracing early in application lifecycle:
```js
client.enable_tracing("openiap=info"); // Options: error, debug, trace
client.disable_tracing();
```
```js
// Custom commands (unstable, may change)
client.custom_command({ command, id, name, data }); // data must be JSON string or ""
// Event handling
client.on_client_event(callback);
client.off_client_event(eventid);
// Utilities
client.uniqeid();
client.formatBytes(bytes, decimals);
client.stringify(obj); // Better error messages than JSON.stringify
// Observable metrics for Grafana
client.set_f64_observable_gauge(name, value, description);
client.set_u64_observable_gauge(name, value, description);
client.set_i64_observable_gauge(name, value, description);
client.disable_observable_gauge(name);
```
```js
const { Client } = require("openiap");
const client = new Client();
await client.connect();
client.enable_tracing("openiap=info");
client.on_client_event((event) => {
if (event && event.event === "SignedIn") {
onConnected().catch((error) => {
client.error(error);
});
}
});
async function onConnected() {
const results = await client.query({
collectionname: "users",
query: "{\"active\": true}",
top: 50
});
client.info("Found users:", results.length);
}
```
```js
const workitem = await client.pop_workitem({ wiq: "processing-queue" });
try {
// Process the work item
const payload = JSON.parse(workitem.payload);
// ... do work ...
workitem.state = "successful";
await client.update_workitem({ workitem });
client.info("Work item completed successfully");
} catch (error) {
client.error("Work item failed:", error);
workitem.state = "retry";
await client.update_workitem({ workitem });
}
```
```js
const watchid = await client.watch(
{ collectionname: "orders", paths: [] },
(event, counter) => {
client.info("Change detected:", event.operation, event.id);
if (event.operation === "insert") {
client.info("New order:", event.document);
}
}
);
```
1. **Always use double quotes** for strings
2. **Never use console.log/console.debug** — use `client.info()` and `client.verbose()`
3. **Always update work item state** after popping and processing
4. **Hook reconnection logic into `SignedIn` events** for stateful operations
5. **Enable tracing early** with `client.enable_tracing()`
6. **All data storage must use OpenIAP MongoDB** via the client library
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/openiap-nodejs-development/raw