Rust Implementation
This is the documentation of the Rust implementation of ivo.
Schemas are declared, not built imperatively: a single attribute macro, #[ivo_schema(...)],
takes a module containing your field declarations and generates the input/output structs, their
partial/error counterparts, and a typed, schema-specific model with create/update/delete
methods.
Installation
Quickstart
use ;
use ivo_schema;
type Timestamp = ;
use ;
create/update/delete are async only if at least one handler they invoke is async --
otherwise the generated method (and any handle_success/handle_failure it returns) is plain
sync, with no runtime dependency forced on you.
Field types
Every field on struct Fields { ... } is declared with exactly one field-type attribute:
| Attribute | Meaning |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --- | ---------------- |
| #[required] | Must be provided at creation; optional (and immutable unless allowed) thereafter. |
| #[lax(default_or_resolver)] | Optional; falls back to a static or resolved default when missing. |
| #[constant(value_or_resolver)] | Output-only; computed once at creation, never accepted from input. |
| #[depends_on("parent", ...)] | Output-only; recomputed via #[resolve(...)] whenever a listed parent field changes. |
| #[ivo_virtual] / #[ivo_virtual("alias")] | Input-only; validated/sanitized like a real field but never stored on the output directly -- typically feeds a #[depends_on(...)] field. |
| #[created_at] / #[updated_at] | Output-only timestamp fields, populated by a schema-level #[timestamps( | | ...)] resolver. |
Each accepts its own set of behavior attributes -- #[validate], #[re_validate], #[sanitize],
#[ignore] / #[ignore_init] / #[ignore_update], #[readonly], #[required(...)] (conditional,
distinct from the #[required] field type), #[on_success] / #[on_failure] / #[on_delete],
and more. See GOAL.md for the full attribute matrix and every allowed combination,
or the runnable examples under examples/ and tests/fields/.
Schema options
Attached to an anonymous const _: () = (); item inside the schema module, not chained onto the
macro call:
// illustrative -- not a continuation of the `post_schema` example above
#[ignore([...], handler)]-- skip a group of#[lax]/#[ivo_virtual]fields together.#[ignore_update([...], handler)]-- same, but update only (or entity-wide with the bare, arrayless form).#[required([...], handler)]-- cross-field "at least one of these" requirement checks.#[post_validate([...], validate = ..., pre_validate = ...)]-- cross-field validation that can also return updated values for the group's own fields.#[on_success(...)]/#[on_delete(...)]-- grouped or entity-wide lifecycle triggers.#[timestamps(|| ...)]-- the shared, synchronous resolver for#[created_at]/#[updated_at].
See GOAL.md §19 for the full reference, including minimum field counts and which
field types each option accepts.
Context options and error sanitizing
ctx_options(YourType) in the macro call threads a value of your own type (dependency injection,
caching, request-scoped data, ...) through every handler in a create/update call, wrapped in a
read/write lock so concurrent handlers can share and mutate it safely -- see
examples/main_demo for a full demo. Pass () when a schema declares
none, as in the quickstart above.
error_sanitizer(YourSanitizer) lets you customize the shape of the error payload returned on
failure by implementing IvoErrorSanitizer -- see
tests/extras/error_sanitizer.rs.