skip to content
sys.name
vvhybe_os 26.10
status
200 building papyrus
user
vvhybe (yassine bouba)

cat odoo-client.ts

04 / 19

@vvhybe/odoo-client

A type-safe JSON-RPC and XML-RPC client for Odoo 14-19, on native fetch.

role
author, maintainer
year
2026
access
-rwxr-xr-x (open source)

TL;DR

problem
Talking to Odoo from JavaScript meant hand-writing JSON-RPC payloads, and every Odoo version moves an endpoint or an argument.
approach
One typed client: an ORM layer that doesn't care which wire is underneath, version quirks handled inside, retries and pagination built in.
outcome
Published on npm under MIT, tested with Vitest in CI, with every release gated on lint, types and tests.

// overview

Talks to Odoo from Node.js, Next.js or React with session, password or API-key auth. Pagination is an async generator, so for await walks a whole model without loading it at once.

Retries use exponential backoff and never retry auth errors. Errors are typed, mapped from Odoo's own exceptions, and the protocol is swappable: the same ORM calls go over JSON-RPC or XML-RPC.

// one ORM, two wires

OdooConnect is the only door. Under it, an ORM service turns search_read, create or write into RPC payloads, and a client sends them: JSON-RPC by default, keeping the session cookie itself in Node, or XML-RPC with protocol: 'xmlrpc'.

Version differences live in one place. Below 16, reads go to the old /web/dataset/search_read; from 19, name_search takes positional arguments. Code that calls the client never has to know.

// retries that know when to stop

Network errors and timeouts retry with exponential backoff. Authentication errors never do: a wrong password won't fix itself, so it surfaces at once.

Odoo's own exceptions come back typed: an odoo.exceptions.AccessError arrives as an OdooAccessError you can catch by class.

// a model of any size

paginate() is an async generator, a hundred records a page by default, so for await walks a whole model without holding it in memory.

// five names in three days

The commit log went Nodoo, Codoo, odoox, odoo-sdk, then @vvhybe/odoo-client. Naming was the hard part. Publishing is guarded: lint, format, typecheck, tests and build all run before npm sees a version.

// stack

  • typescript
  • node 18+
  • vitest
  • json-rpc
  • xml-rpc

// links