Files
invoiceninja-sdk/CLAUDE.md
T
awkawbandClaude Opus 5 ff9a859d0b
CI / test (push) Canceled after 0s
Initial commit: async Rust client for the Invoice Ninja v5 API
Covers Clients, Invoices, Quotes, Credits, Payments, Products, Expenses,
Projects, Tasks, and Vendors, each with list, list_all, get, create,
update, and delete, generated by the resource_methods! macro.

Every model carries a #[serde(flatten)] extra map so fields the API
returns but the crate does not model survive a get/update round-trip
instead of being silently dropped.

Includes a Nix dev shell (Rust via rust-overlay), a GitHub Actions CI
workflow running build/test/fmt/clippy, and round-trip tests for the
extra-preservation invariant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-23 14:30:01 -04:00

73 lines
3.0 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
An async Rust client for the [Invoice Ninja](https://www.invoiceninja.com/) v5 API.
## Development environment
This project uses Nix for toolchain management (Rust via `rust-overlay`):
```sh
nix develop
```
## Common commands
```sh
cargo build
cargo test
cargo test <test_name> # run a single test
cargo check
cargo clippy
cargo fmt
# Run the example (requires IN_API_TOKEN, optionally IN_BASE_URL)
IN_API_TOKEN=... cargo run --example list_clients
```
Tests live in `tests/` (integration-style, no network access required);
`src/` has no `#[test]` modules.
## Architecture
- `src/client.rs` — `InvoiceNinjaClient` holds a `reqwest::Client` (with the
`X-Api-Token` auth header baked in) and a `base_url`. Low-level helpers
(`get_list`, `get_one`, `post_one`, `put_one`, `delete_one`) handle request
dispatch and decode `ListResponse<T>` / `ItemResponse<T>` envelopes, mapping
non-2xx responses through `api_error` into `Error::Api`.
- Per-resource methods (`list_clients`, `get_invoice`, `create_product`, etc.)
are generated by the `resource_methods!` macro at the bottom of
`client.rs`, which expands to
`list`/`list_all`/`get`/`create`/`update`/`delete` for a given REST path and
model type. **To add a new resource**: add a model under `src/models/`,
re-export it from `src/models/mod.rs`, and add one `resource_methods!`
invocation in `client.rs`. Note the macro takes six method names before the
path and model — adding a resource means passing all six.
- `list_*` returns one page; `list_all_*` goes through `get_all_pages`, which
follows `page`/`per_page` until a page returns fewer rows than requested.
- `src/models/` — one file per resource (`client.rs`, `invoice.rs`,
`payment.rs`, `product.rs`, `expense.rs`, `project.rs`, `task.rs`,
`vendor.rs`), plus `common.rs` for shared envelope/pagination types
(`ListParams`, `ListResponse`, `ItemResponse`, `Meta`, `Pagination`).
Invoice Ninja stores quotes and credits in the same table as invoices (an
`entity_type` field distinguishes them), so `Quote` and `Credit` are type
aliases for `Invoice` (`src/models/invoice.rs`) and share the
`/quotes`, `/credits`, and `/invoices` paths via the macro.
- Every model struct has a `#[serde(flatten)] pub extra: Map<String, Value>`
field. This preserves any API fields not explicitly modeled, so a `get`
followed by an `update` round-trips without silently dropping data. Keep
this pattern when adding fields or new models.
- `src/error.rs` — `Error` enum (`thiserror`) covering transport, JSON
decode, API error responses (with per-field validation `errors` map), and
client construction errors. `ApiErrorBody` mirrors Invoice Ninja's error
JSON shape.
## Coverage
Clients, Invoices, Quotes, Credits, Payments, Products, Expenses, Projects,
Tasks, and Vendors, each with `list`, `list_all`, `get`, `create`, `update`,
and `delete`.