Expands coverage to every `Route::resource` group in the v5 API plus `users` (265 methods), and fixes several defects in the shared request path that the new breadth made more exposed. Coverage: - 25 new models, each keeping the `extra` flatten map and the `null_to_default` convention so unmodeled fields round-trip. - `crud_methods!` split out of `resource_methods!` for the three groups with no `/bulk` route, where a generated `bulk_*` would only 405. - COVERAGE.md added as the detailed inventory, verified against `routes/api.php` on v5-stable. Fixes, each confirmed against upstream source or an observed request: - `list_all_*` silently truncated. `BaseController` caps page size at `min(abs(per_page), 5000)`, so the "short page means last page" rule stopped early and returned a partial list as if complete. Termination now prefers `meta.pagination.total_pages` (decoded but previously discarded), and `per_page` is clamped so the fallback stays sound. - `per_page(0)` paged forever: the check `got < 0` has no solution. It now falls back to the default size, with a MAX_PAGES backstop that raises `Error::PaginationLimit` rather than quietly truncating. - Ids were interpolated into paths raw, so a `/` or `?` in an id retargeted the request. All sites now use `seg(id)?`. Escaping alone is insufficient: the WHATWG rules `url` implements decode `%2E` to `.` before resolving dot segments, so an escaped `..` still collapses the path. Empty and dot-only ids are rejected. - No request timeout. reqwest applies none, so a stalled connection hung the caller indefinitely. Adds a 60s default and `with_timeout`. - Base URL is validated at construction; a missing scheme used to 404 on every call instead of failing once. Adds tests/client_requests.rs: 26 tests over the request plumbing against a wiremock loopback server, including regressions for the truncation and non-termination bugs. No network or credentials needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
25 lines
880 B
TOML
25 lines
880 B
TOML
[package]
|
|
name = "invoiceninjars"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
description = "An async Rust client for the Invoice Ninja v5 API"
|
|
license = "MIT"
|
|
repository = "https://github.com/bryant/invoiceninjars"
|
|
|
|
[dependencies]
|
|
reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
thiserror = "2"
|
|
# Already in the tree via reqwest's `url`; used to escape ids before they are
|
|
# interpolated into request paths.
|
|
percent-encoding = "2"
|
|
|
|
[dev-dependencies]
|
|
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
|
|
# Used to assert that ListParams urlencodes the way reqwest will send it.
|
|
serde_urlencoded = "0.7"
|
|
# Loopback HTTP server for exercising the request plumbing (pagination, path
|
|
# escaping, headers, error mapping) without reaching the network.
|
|
wiremock = "0.6"
|