Node-RED
@onerp/node-red (packages/node-red) is a Node-RED palette for calling into
OnERP: reading and writing business object records and invoking operations.
It is call-only — OnERP does not push events, so a flow triggers from
Node-RED’s own side (inject, cron, MQTT, http in) and then talks to OnERP.
Under the hood every node runs on @onerp/client, authenticated with a
service-account API key.
Install
Section titled “Install”The package depends on workspace packages, so a plain
npm install <path> cannot resolve it. pnpm deploy materializes a
self-contained copy first:
pnpm turbo build --filter=@onerp/node-redpnpm --filter @onerp/node-red deploy --prod --legacy /tmp/onerp-node-redcd ~/.node-red && npm install /tmp/onerp-node-redRestart Node-RED; the three flow nodes appear under the OnERP category.
Developing the nodes
Section titled “Developing the nodes”For working on the package itself, skip the deploy: pnpm --filter @onerp/node-red dev:red starts a local Node-RED on :1880 that loads the
nodes straight from the source tree (nodesDir), with its flows kept in a
gitignored .node-red/ inside the package. Run pnpm --filter @onerp/node-red dev alongside for the TypeScript watch, and restart Node-RED to pick up a
rebuilt node.
Connection
Section titled “Connection”Every flow node points at an onerp-config node holding the server’s base URL
and an API key. Create the key under Settings → Service Accounts — its role
decides what the flows may do. The key is stored in Node-RED’s encrypted
credentials store, not in the flow export.
The connection builds its client when the flow deploys: a wrong URL or key fails loudly at deploy time (red node status), not at 3am mid-flow. The workspace’s meta is loaded at the same moment and stays fixed until the next deploy — a domain deployed to the server later is not visible to running flows until Node-RED redeploys.
The nodes
Section titled “The nodes”Identity lives in the editor (business object, mode, operation); data rides
the message. Records cross into flows as plain wire JSON — decimals and dates
are strings, safe for debug, switch and template nodes.
onerp read
Section titled “onerp read”| Mode | In | Out (msg.payload) |
|---|---|---|
| get | msg.id |
the record; null when missing (not an error) |
| list | msg.payload = { filter?, sort?, cursor?, limit?, withTotal? } (optional) |
{ items, nextCursor, total? } — feed nextCursor back as cursor to page on |
onerp write
Section titled “onerp write”| Mode | In | Out (msg.payload) |
|---|---|---|
| create | msg.payload = record |
the created record |
| update | msg.id + msg.payload = patch |
the updated record |
| delete | msg.id |
payload passes through unchanged |
onerp call
Section titled “onerp call”| Target | In | Out (msg.payload) |
|---|---|---|
function — Operation = namespace/name, Business Object empty |
msg.payload = params |
the result; null when the operation returns nothing |
| bound action — Business Object set, Operation = action name | msg.id + msg.payload = params |
same |
Errors
Section titled “Errors”A failed request raises through the node’s error path, so a catch node
routes it like any other flow error. When the failure is an OnERP error
response, the message additionally carries the structured body:
{ "onerpError": { "code": "core.forbidden", "status": 403, "detail": "…" } }The node’s status dot mirrors the last outcome — green ok, red with the
error code. There are no retries; Node-RED’s own catch/retry patterns apply.