Hubuum client library (Rust)
A Rust client library for interacting with the Hubuum API. The library is designed to be both flexible and safe, employing a type state pattern for authentication and offering both synchronous and asynchronous interfaces.
Features
-
Type State Pattern for Authentication:
The client is built around a type state pattern. A new client instance is initially in an unauthenticated state (i.e.
Client<Unauthenticated>) and only exposes the login interface. Once authenticated (via username/password or token), the client transitions toClient<Authenticated>, unlocking the full range of API operations. -
Dual-Mode Operation:
Choose between a synchronous (blocking) or asynchronous (non-blocking) client depending on your application needs.
-
Configurable Client Setup:
Use
SyncClient::new(base_url)for secure defaults, or the explicitnew_with_certificate_validation/new_without_certificate_validationconstructors when needed. -
Comprehensive API Access:
Easily interact with resources such as classes, class relations, and other Hubuum API endpoints with well-defined method chains for filtering and execution.
-
Reports, Templates, and Imports:
Run server-side reports, manage stored report templates, and submit asynchronous imports with typed task polling helpers.
-
No Built-In Table Formatting:
Models no longer implement built-in table rendering traits. Consumers that want table support should wrap/newtype the exported models in their own crates.
Installation
Add the dependency to your project's Cargo.toml:
[]
= "0.0.2"
If you need unreleased changes, you can still point Cargo at the Git repository:
[]
= { = "https://github.com/terjekv/hubuum-client-rust" }
Usage
The library offers both a sync and an async client. The interface for both is similar, but the async client adds await syntax for asynchronous operations.
It is safe to clone() the client if need be.
Synchronous Client
The synchronous client provides a blocking interface that is ideal for simpler or legacy applications.
Client Initialization and Authentication
use FromStr;
use ;
Making API Calls
Once authenticated, you can perform operations against the API. For example, to create a new class resource:
let result = client
.classes
.create
.name
.namespace_id
.description
.send?;
The fluent API works across create/update/query flows. If needed, you can still pass raw structs through create_raw, update_raw, and query().params(...).
Searching Resources
The client’s API is designed with a fluent query interface. For example, to search for a class by its exact name:
let name = "example-class";
let class = client
.classes
.query
.name_eq
.one?;
Or, to find a relation between classes:
let relation = client
.class_relation
.query
.add_filter_equals
.add_filter_equals
.one?;
Related-object traversal now follows the dedicated related/* endpoints, including graph fetches and endpoint-specific result filters:
let related = object
.related_objects
.ignore_classes
.ignore_self_class
.add_filter_equals
.limit
.page?;
let graph = object
.related_graph
.add_filter_equals
.fetch?;
Asynchronous Client
The asynchronous client leverages Rust’s async/await syntax and is built for high-concurrency applications using runtimes like Tokio.
Async Client Initialization and Authentication
use FromStr;
use ;
async
As one can see, the interface is very similar to the synchronous client.
Reports and Templates
Templates are exposed as a regular resource:
let template = client
.templates
.create
.namespace_id
.name
.description
.content_type
.template
.send?;
Report execution is exposed through client.reports() and returns a typed ReportResult:
let report = client.reports.run?;
match report
Imports and Tasks
Imports return task-shaped responses and can be polled through client.imports() and client.tasks():
let task = client
.imports
.submit
.idempotency_key
.send?;
let task_state = client.tasks.get?;
let event_page = client.tasks.events.limit.page?;
let result_page = client.imports.results.limit.page?;
Cursor-paged endpoints return hubuum_client::Page<T> with items and next_cursor.
Unified Search
Grouped discovery searches are exposed through client.search(...):
let search = client
.search
.kinds
.limit_per_kind
.search_object_data
.execute?;
for object in search.results.objects
let events = client
.search
.kinds
.stream?;
Integration Tests (Real Server)
The repository includes an opt-in Docker-backed integration test suite in
tests/container_integration.rs.
Recommended entrypoint:
The script starts one PostgreSQL container and one Hubuum server container, waits for readiness,
optionally applies SQL seed data, runs integration tests, and tears everything down in a shell
trap (unless keep mode is enabled).
Mutating integration tests use unique itest-<case>-<ts> resource name prefixes, so they are safe
to run with default parallel test threads.
Seed behavior:
- default seed file:
tests/container_integration/seed/init.sql - custom seed file:
./scripts/run-integration-tests.sh --seed path/to/seed.sql - disable seeding:
./scripts/run-integration-tests.sh --skip-seed
External stack mode:
- tests can reuse an externally managed stack when both env vars are set:
HUBUUM_INTEGRATION_BASE_URLHUBUUM_INTEGRATION_ADMIN_PASSWORD
- this is what the wrapper script exports internally before running tests.
Optional environment variables:
HUBUUM_INTEGRATION_SERVER_IMAGEto override the server imageHUBUUM_INTEGRATION_DB_IMAGEto override the database imageHUBUUM_INTEGRATION_STACK_TIMEOUT_SECSto override startup timeout (default:300)HUBUUM_INTEGRATION_KEEP_CONTAINERS=1to keep containers running for debuggingHUBUUM_INTEGRATION_SEED_SQLto override the default seed SQL file
If the server image is private in your environment, authenticate first:
Contributing
Contributions are welcome! If you find issues or have suggestions for improvements, please open an issue or submit a pull request on GitHub.
Release notes live in CHANGELOG.md, and the release procedure for crates.io publishing is documented in RELEASING.md.
License
Distributed under the MIT License. See LICENSE for more details.