Skip to main content

Macros

Declarative macros are exported from riverbase_core (and its prelude). The two procedural macros live in riverbase_proc. When a macro produces a confusing error, run cargo expand on the crate to see the generated code.

domain!​

riverbase_core::domain! {
domain <Name> {
meta { namespace: "<ns>", title: "<title>", description: "<text>" }
command: <CommandEngine>, // optional (query-only domains)
query: <QueryEngine>,
service: <ServiceEngine>, // optional
routes(<api_base>) { <axum::Router expr> } // optional; needs `http`
spawn(runtime: &DomainRuntime) { <body returning RiverbaseResult<Self>> }
}
}

The generated <Name><S> has NAMESPACE, spawn, engine_context, from_engines, from_query, into_arc, command(), query(), service(), execute_command, execute_query, and implements Domain. See Domains.

command_engine! / command!​

riverbase_core::command_engine! {
engine <Name> {
domain_trait: generate | manual, // optional
meta { command_pool_size: <n> }, // optional; actor_pool_size alias
aggregate: <Aggregate>,
component: { <field>: <Type>, … },
}
commands {
command <PascalName> {
meta {
key: "<cmdkey>", title: "<title>", kind: collection | object, resources: [<expr>, …],
// optional: scope: required, link: true, hook: true, tenant_scope: exempt,
// engine_method: false, response_type: "…", openapi_tag: "…", …
}
payload { <field>: <Type>, … }
target collection(<resource>) | object(<resource>); // optional
handle (<payload>, <aggregate>) { <body> }
}
}
methods ( // optional
<name>(<arg>: [<Type>]; …) for <PascalName> {
payload <PayloadType> { … },
target none | some(<CommandTarget expr>)
}
)
}

The commands-only form, command_engine! { commands <Aggregate> { … } }, generates handlers and a register_<aggregate>_handlers(&mut args) function. See Commands.

impl_domain_command_engine!(<Engine>) writes a forwarding DomainCommandEngine impl for engines declared with domain_trait: manual that need no custom behavior.

query_resource!​

riverbase_core::query_resource! {
<Name> name "<resource>" {
meta {
title: "<title>", description: "<text>",
default_order: [<field>.asc | <field>.desc, …],
scope: none | required,
// optional: order_fields: [<field>, …]
}
fields {
field <name> { preset: <Preset>, label: "<label>" [, identifier] [, sortable | no_sort] }
}
binding source "<table>" { <field> => "<column>", … }
errors { list: ("<CODE>", "<message>"), item: ("<CODE>", "<message>") }
policy: required | optional | public("<reason>", "<sign-off>"),
scope_policy(<ctx>, <url_scope>) { <RiverbaseResult<Option<Expr>>> } // optional
tenant_scope: exempt("<reason>", "<sign-off>"), // optional
}
}

Presets: Uuid, String, Integer, Number, Boolean, Datetime, Date, Enum, Array, Json, Textsearch, None. It also generates <Name>Key, a typed resource key.

report_resource!​

Same shape as query_resource!, with filters { field … } instead of fields, plus:

params { param <name> { type: <Date|…>, label: "<label>" [, required] } }
errors { report: ("<CODE>", "<message>") }
handler (<self>, <ctx>, <session>, <request>, <query>) { <RiverbaseResult<ReportOutput>> }

query_engine!​

riverbase_core::query_engine! {
engine <Name> {
meta { query_pool_size: <n> }, // actor_pool_size alias
component: { … },
}
resources { <Resource>, … }
reports { <Report>, … } // optional
}

Persistence macros​

MacroPurpose
diesel_table_with_domain_fields! { schema.table (_id) { col -> Type, … } }Diesel table! plus the domain columns
domain_row! { #[derive(…)] pub struct Row { … } }A row struct with domain fields prepended
pg_domain_entity! { Name { schema, row, resources, source, row_to_json, upsert_from_json, order } }A writable Postgres entity
pg_readonly_entity! { … }A read-only entity, for views and reports
domain_insert_values!(table, domain, col.eq(v), …)Insert values including the domain columns
domain_json_converters!Row-to-JSON helpers

Other declarative macros​

MacroPurpose
declare_errors! { type_base: "…", CODE { status, title, code, message, hint } … }A crate error catalogue. See Errors.
aggregate_core_deref!(Aggregate)Deref/DerefMut to AggregateCore
resource_name!(…)A ResourceName from a literal

Procedural macros (riverbase_proc)​

MacroPurpose
#[domain_action(event = "…", resources = ["…"])]Mark an aggregate method as a state-changing action. See riverbase_proc.
riverbase_namespace!("…")A Namespace from a literal