eventide-macros 0.1.1

Procedural macros for the eventide DDD/CQRS toolkit: derive entities, entity ids, value objects and domain events with a single attribute.
Documentation

eventide-macros

Crates.io Documentation

中文版本: README.zh.md

Procedural macros that generate the boilerplate around the eventide DDD/CQRS toolkit: #[entity], #[entity_id], #[domain_event], #[value_object].

Generated code uses the absolute path ::eventide_domain::.... The companion crate eventide-domain declares extern crate self as eventide_domain; so the macros also resolve inside its own tests and examples.

Default derives

The macros merge user-supplied derives with sensible defaults so you rarely have to repeat the same list:

Macro Auto-applied derives
#[entity] Debug*, Default, serde::Serialize, serde::Deserialize
#[entity_id] Default, Clone, Debug*, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash
#[domain_event] Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize
#[value_object] Default, Clone, Debug*, serde::Serialize, serde::Deserialize, PartialEq, Eq

* = can be turned off with debug = false.

Make sure serde is in your dependency tree with the derive feature:

[dependencies]
serde = { version = "1", features = ["derive"] }

#[entity]

Apply to a named-field struct. The macro:

  • Adds id: IdType and version: usize if missing, ordered first.
  • Implements Entity with new / id / version.
  • Merges in the default derives (deduplicated).
#[entity(id = AccountId)]              // id type defaults to String when omitted
#[entity(debug = false)]                // opt out of automatic Debug derive
struct BankAccount {
    balance: i64,
}

Restrictions: named-field struct only.

#[entity_id]

Apply to a single-field tuple struct (e.g. struct AccountId(String);). The macro:

  • Implements FromStr (delegated to the inner type) and Display.
  • Provides pub fn new(value: Inner) -> Self.
  • Adds bidirectional conversions (AsRef, AsMut, From<&Self> for Inner, etc.).
  • Merges in the default derives.
#[entity_id]
struct AccountId(String);

Restrictions: tuple struct with exactly one field.

#[domain_event]

Apply to an enum whose variants use named fields. The macro:

  • Adds id: IdType and aggregate_version: usize to each variant if missing.
  • Implements DomainEvent.
  • Sets the event type to EnumName.Variant by default; override per variant.
  • Sets the event version from the enum-level version argument; override per variant.
#[domain_event(id = String, version = 1)]
enum BankAccountEvent {
    #[event(event_type = "bank_account.deposited")]
    Deposited { amount: i64 },

    #[event(event_type = "bank_account.withdrawn", event_version = 2)]
    Withdrawn { amount: i64 },
}

Per-variant overrides are written as #[event(event_type = "...", event_version = N)].

#[value_object]

Apply to a struct (named-field or tuple) or an enum. The macro merges in the default derives without changing the existing fields/variants.

#[value_object]
struct Money {
    amount: i64,
    currency: String,
}

#[value_object(debug = false)]
struct Amount(i64);

#[value_object]
enum Level {
    #[default]
    Low,
    High,
}

If the target is an enum and Default is enabled (the default), one variant must be marked with #[default].

UI tests

cargo test -p eventide-macros

The crate uses trybuild to verify that the generated code compiles for representative inputs. Test cases live under tests/ui/.

Layered architecture

eventide-application  →  eventide-domain  ←  eventide-macros

eventide-macros only emits domain-layer items, keeping infrastructure concerns out of generated code.

License

Licensed under either of Apache-2.0 or MIT at your option.